Subqueries - 96ankur/SQL GitHub Wiki

Subqueries

  • It is a SELECT statment within anyother query.
    SELECT *
    FROM employees
    WHERE salary > (
    	SELECT AVG(salary)
        FROM employees
    )
    
  • This is first syntax of writing subquery.

Subquery with IN operator

  •   SELECT *
      FROM clients
      WHERE client_id NOT IN(
      	SELECT DISTINCT client_id 
          FROM invoices
      )
    

Subquery vs Joins

  • With subquery
    SELECT customer_id, first_name, last_name
    FROM customers
    WHERE customer_id IN(
    	SELECT DISTINCT customer_id
    	FROM orders
    	WHERE order_id IN (
    		SELECT order_id
    		FROM order_items
    		WHERE product_id = 3
    	)
    )
    
  • With joins
    SELECT DISTINCT customer_id, first_name, last_name 
    FROM customers c
    JOIN orders o
    		USING (customer_id)
    JOIN order_items oi
    		USING (order_id)
    WHERE product_id=3
    

ALL clause

  • SELECT * 
    FROM invoices
    WHERE invoice_total > ALL (
    		SELECT invoice_total
    		FROM invoices
    		WHERE client_id = 3
    )
    

ANY clause

  •   SELECT *
      FROM clients
      WHERE client_id = ANY (      -- in place of = ANY, IN operator can all be used
      		SELECT client_id
      		FROM invoices
      		GROUP BY client_id
      		HAVING COUNT(*) >= 2
      )
    

Correlated Subquery

  • In correlated subquery, the subquery is executed for each record of the outer query.
    SELECT *
    FROM employees e
    WHERE salary >(
    		SELECT AVG(salary)
    		FROM employees
            WHERE office_id = e.office_id
    )
    

Exists operator

  •   SELECT client_id, name 
      FROM clients
      WHERE client_id IN (
      	SELECT DISTINCT client_id 
          FROM invoices
      );
    
    
  • The above query should only be used when the result of the subquery is less. But if the result of the subquery is very large then this query leads to performance issues. In that case we can use EXIXTS operator

  •   SELECT client_id, name 
      From clients c
      WHERE EXISTS (
      	SELECT client_id 
          FROM invoices
          WHERE client_id = c.client_id
      );
    

Subquery in SELECT clause

  • SELECT client_id,
       name,
       (SELECT SUM(invoice_total) 
    		FROM invoices
    		WHERE client_id = c.client_id)AS total_sales,
       (SELECT AVG(invoice_total)FROM invoices) AS average,
       (SELECT total_sales - average) AS difference
    FROM clients c
    

Subquery in FROM clause

  • Useful only for simple queries.
    SELECT * 
    FROM (
    SELECT client_id,
    	   name,
           (SELECT SUM(invoice_total) 
    			FROM invoices
    			WHERE client_id = c.client_id)AS total_sales,
           (SELECT AVG(invoice_total)FROM invoices) AS average,
            (SELECT total_sales - average) AS difference
    FROM clients c
    ) AS sales_summary   -- this alias is mandatory
    WHERE total_sales IS NOT NULL
    

IFNULL and COALESCE function

  • SELECT CONCAT(first_name, last_name) AS customer,
       IFNULL(phone, "Unknown"),
       COALESCE(phone, "Unknown") -- it can take 3 parameters
    FROM customers;
    

IF function

  • SELECT *,
    	   IF(orders > 1, "Many times", "Once") AS frequency
    FROM (
    	SELECT product_id,
    		   name,
    		   COUNT(product_id) AS orders
    	FROM order_items oi
    	JOIN products p USING (product_id)
    	GROUP BY product_id, name
    ) AS product_data
    

CASE operator

  • SELECT CONCAT(first_name, last_name) AS customer,
    	   points,
           CASE
    			WHEN points > 3000 THEN 'Gold'
                WHEN points >= 2000 THEN 'Silver'
                ELSE 'Bronze'
    		END AS category
    FROM sql_store.customers
    ORDER BY points DESC