@@ -698,15 +698,176 @@ FROM city
698698WHERE countrycode= ' BEL' OR countrycode= ' TUN' OR countrycode= ' NL' ;
699699
700700
701+ /* ----------------------------------------------------------------------------------------------------------- */
701702
703+ /* ********************* 27) Subqueries ************************/
704+ /*
705+ Subqueries can be used in SELECT, FROM, HAVING, WHERE.
706+
707+ For HAVING and WHERE clause, subquery must return SINGLE value record.
708+ */
702709
710+ SELECT
711+ title, price,
712+ (SELECT AVG (price) FROM products) AS " global average price"
713+ FROM products;
703714
704715
716+ -- Subquery can returns A Single Result or Row Sets
717+ SELECT
718+ title, price,
719+ (SELECT AVG (price) FROM products) AS " global average price" -- return single result
720+ FROM (
721+ SELECT * FROM products -- return row sets
722+ ) AS " products_sub" ;
723+
724+ /* *********** 29) Types of Subqueries *************/
725+ /*
726+ Single Row
727+ Multiple Row
728+ Multiple Column
729+ Correlated
730+ Nested
731+ */
732+
733+ -- Single Row: returns Zero or One Row
734+ SELECT emp_no, salary
735+ FROM salaries
736+ WHERE salary > (
737+ SELECT AVG (salary) FROM salaries
738+ );
705739
740+ -- Multiple Row: returns One or More Rows
741+ SELECT title, price, category
742+ FROM products
743+ WHERE category IN (
744+ SELECT category FROM categories
745+ WHERE categoryname IN (' Comedy' , ' Family' , ' Classics' )
746+ );
706747
748+ -- Multiple Columns: returns ONE or More columns
749+ SELECT emp_no, salary, dea .avg AS " Department average salary"
750+ FROM salaries s
751+ JOIN dept_emp as de USING(emp_no)
752+ JOIN (
753+ SELECT dept_no, AVG (salary) FROM salaries AS s2
754+ JOIN dept_emp AS de2 USING(emp_no)
755+ GROUP BY dept_no
756+ ) AS dea USING (dept_no)
757+ WHERE salary > dea .avg ;
758+
759+
760+ -- Correlated: Reference ONE or More columns in the OUTER statement - Runs against Each Row
761+ /* Get the most recent salary of employee */
762+ SELECT emp_no, salary AS " most recent salary" , from_date
763+ FROM salaries AS s
764+ WHERE from_date = (
765+ SELECT MAX (s2 .from_date ) AS max
766+ FROM salaries AS s2
767+ WHERE s2 .emp_no = s .emp_no
768+ )
769+ ORDER BY emp_no;
707770
708771
772+ -- Nested : Subquery in Subquery
773+ SELECT orderlineid, prod_id, quantity
774+ FROM orderlines
775+ JOIN (
776+ SELECT prod_id
777+ FROM products
778+ WHERE category IN (
779+ SELECT category FROM categories
780+ WHERE categoryname IN (' Comedy' , ' Family' , ' Classics' )
781+ )
782+ ) AS limited USING(prod_id);
709783
784+ /* ************** 30) Using Subqueries ************/
785+ SELECT
786+ first_name,
787+ last_name,
788+ birth_date,
789+ AGE(birth_date)
790+ FROM employees
791+ WHERE AGE(birth_date) > (SELECT AVG (AGE(birth_date)) FROM employees);
792+
793+
794+ /* Show the salary with title of the employee using Subquery, instead of JOIN */
795+ SELECT emp_no, salary, from_date,
796+ (SELECT title FROM titles AS t
797+ WHERE t .emp_no = s .emp_no AND t .from_date = s .from_date )
798+ FROM salaries s
799+ ORDER BY emp_no;
710800
801+ EXPLAIN ANALYZE
802+ SELECT emp_no, salary AS " most recent salary" , from_date
803+ FROM salaries AS s
804+ WHERE from_date = (
805+ SELECT MAX (s2 .from_date ) AS max
806+ FROM salaries AS s2
807+ WHERE s2 .emp_no = s .emp_no
808+ )
809+ ORDER BY emp_no;
711810
712811
812+ /* ********************* 32) Subqueries Operators *******************/
813+ /*
814+ EXISTS : Check if the subquery returns any rows
815+ */
816+ SELECT firstname, lastname, income
817+ FROM customers AS c
818+ WHERE EXISTS(
819+ SELECT * FROM orders as o
820+ WHERE c .customerid = o .customerid AND totalamount > 400
821+ ) AND income > 90000
822+
823+ /*
824+ IN : Check if the value is equal to any of the rows in the return (NULL yields NULL)
825+ NOT IN : Check if the value is NOT equal to any of the rows in the return (NULL yields NULL)
826+ */
827+ SELECT prod_id
828+ FROM products
829+ WHERE category IN (
830+ SELECT category FROM categories
831+ WHERE categoryname IN (' Comedy' , ' Family' , ' Classics' )
832+ );
833+
834+
835+ SELECT prod_id
836+ FROM products
837+ WHERE category IN (
838+ SELECT category FROM categories
839+ WHERE categoryname NOT IN (' Comedy' , ' Family' , ' Classics' )
840+ );
841+
842+ /*
843+ ANY / SOME : check each row against the operator and if any comparison matches, return TRUE.
844+ */
845+
846+ SELECT prod_id
847+ FROM products
848+ WHERE category = ANY(
849+ SELECT category FROM categories
850+ WHERE categoryname IN (' Comedy' , ' Family' , ' Classics' )
851+ );
852+
853+ /*
854+ ALL : check each row against the operator and if all comparisions match, return true.
855+ */
856+ SELECT prod_id, title, sales
857+ FROM products
858+ JOIN inventory as i USING(prod_id)
859+ WHERE i .sales > ALL(
860+ SELECT AVG (sales) FROM inventory
861+ JOIN products as p1 USING(prod_id)
862+ GROUP BY p1 .category
863+ );
864+
865+ /*
866+ Single Value Comparison
867+ */
868+ SELECT prod_id
869+ FROM products
870+ WHERE category = (
871+ SELECT category FROM categories
872+ WHERE categoryname IN (' Comedy' )
873+ );
0 commit comments