Monday, June 22, 2020

SQL - Subquery Has 'One Expression' Without Order BY


1         
PLAYER1   
MARIO     
2         
PLAYER2   
CS        
3         
PLAYER1   
MINECRAFT
4         
PLAYER1   
DOTA      
5         
PLAYER1   
STARWAR   
6         
PLAYER2   
OXENFREE  
NULL
NULL
NULL

--SQL 'ORDER BY' Not Allowed In Subquery
SELECT TOP 30 PERCENT *
FROM
    (SELECT username, COUNT(*) AS C
     FROM plays
     GROUP BY username
     ORDER BY username DESC) T

--Move The 'Order By' To Outside The Subquery
SELECT TOP 30 percent *
FROM
    (SELECT username, COUNT(*) AS c
     FROM plays
     GROUP BY username
     ) T
ORDER BY  c DESC

--Put It All Together
SELECT TOP 30
  username,
  count(*) AS n_plays
FROM plays
GROUP BY username
ORDER BY n_plays DESC;


SELECT * FROM plays
WHERE plays.username
IN (SELECT TOP 30
                username,
                COUNT(*) AS n_plays
        FROM plays
        GROUP BY username
        ORDER BY n_plays DESC
        )
--Output
--(Subquery That Should Return One Column But Is Returning Two)
--PLAYER1       4
--PLAYER2       2
--ERROR - Only one expression can be specified in the select list
--        when the subquery is not introduced with EXISTS.


--OR THE SOLUTION

SELECT * FROM plays
WHERE plays.username
IN (SELECT TOP 30
                username
                --COUNT(*) AS n_plays
        FROM plays
        GROUP BY username
        --ORDER BY n_plays DESC
        )
--PLAYER1  
--PLAYER2

--Alternative
SELECT u.*
FROM plays u JOIN
     (SELECT TOP 30 username, COUNT(*) AS n_plays
      FROM plays p
      GROUP BY p.username
      ORDER BY COUNT(*) DESC
     ) pu
ON pu.username = u.username; 

Monday, June 15, 2020

SQL - COALESCE


COALESCE (Transact-SQL)
Evaluates the arguments in order and returns the current value of the first expression that initially doesn't evaluate to NULL. For example, SELECT COALESCE(NULL, NULL, 'third_value', 'fourth_value'); returns the third value because the third value is the first value that isn't null.

CREATE TABLE dbo.wages 
( 
    emp_id        tinyint   identity, 
    hourly_wage   decimal   NULL, 
    salary        decimal   NULL, 
    commission    decimal   NULL, 
    num_sales     tinyint   NULL 
); 
GO 
INSERT dbo.wages (hourly_wage, salary, commission, num_sales) 
VALUES 
    (10.00, NULL, NULL, NULL), 
    (20.00, NULL, NULL, NULL), 
    (30.00, NULL, NULL, NULL), 
    (40.00, NULL, NULL, NULL), 
    (NULL, 10000.00, NULL, NULL), 
    (NULL, 20000.00, NULL, NULL), 
    (NULL, 30000.00, NULL, NULL), 
    (NULL, 40000.00, NULL, NULL), 
    (NULL, NULL, 15000, 3), 
    (NULL, NULL, 25000, 2), 
    (NULL, NULL, 20000, 6), 
    (NULL, NULL, 14000, 4); 
GO 
SET NOCOUNT OFF; 
GO 
SELECT CAST(COALESCE(hourly_wage * 40 * 52,  
   salary,  
   commission * num_sales) AS money) AS 'Total Salary'  
FROM dbo.wages 
ORDER BY 'Total Salary'; 
GO 


1.      Because ISNULL is a function, it's evaluated only once. The input values for the COALESCE expression can be evaluated multiple times.
2.      Data type determination of the resulting expression is different. ISNULL uses the data type of the first parameter, COALESCE follows the CASE expression rules and returns the data type of value with the highest precedence.
3.     The NULLability of the result expression is different for ISNULL and COALESCE. The ISNULL return value is always considered NOT NULLable (assuming the return value is a non-nullable one). By contrast, COALESCE with non-null parameters is considered to be NULL. So, the expressions ISNULL(NULL, 1) and COALESCE(NULL, 1), although equal, have different nullability values.
4.      Validations for ISNULL and COALESCE are also different. For example, a NULL value for ISNULL is converted to int though for COALESCE, you must provide a data type.
5.      ISNULL takes only two parameters. By contrast COALESCE takes a variable number of parameters.

Sunday, June 14, 2020

SQL - MULTIPLE COUNT OR SUM CASE WHEN


Multiple COUNT 

SELECT Approved  = (SELECT COUNT(*) FROM dbo.Claims d
                    WHERE d.Status = 'Approved'),
        Valid    = (SELECT COUNT(*) FROM dbo.Claims d
                    WHERE d.Status = 'Valid'),
        Reject   = (SELECT COUNT(*) FROM dbo.Claims d
                    WHERE d.Status = 'Reject')

SUM CASE WHEN

SELECT  Approved = SUM(CASE WHEN Status = 'Approved' THEN 1 ELSE 0 END),
        Valid    = SUM(CASE WHEN Status = 'Valid'    THEN 1 ELSE 0 END),
        Reject   = SUM(CASE WHEN Status = 'Reject'   THEN 1 ELSE 0 END)
FROM dbo.Claims c;

SELECT  Approved = SUM(CASE WHEN Status = 'Approved' THEN 1 ELSE 0 END),
        Valid    = SUM(CASE WHEN Status = 'Valid'    THEN 1 ELSE 0 END),
        Reject   = SUM(CASE WHEN Status = 'Reject'   THEN 1 ELSE 0 END)
FROM dbo.Claims c
WHERE  c.Status = 'Approved'
    OR c.Status = 'Valid'
    OR c.Status = 'Reject';