Search code examples
sqlms-accesssubqueryleft-joinms-access-2016

LEFT JOIN multiple sub queries


My intention is to create a table with the number of orders and revenue for two different years for every product. My idea was to use a double left Join but I don't understand why this query does not work on MS ACCESS. I decided to use LEFT JOIN because in the subquery per year some products may not appear if it was not ordered. The Subqueries a and b are OK. They work separately. What's the problem with this query?

SELECT p.PK_Product_ID, a.[2013_Orders], a.[2013_Gross_Value], b.[2014_Orders], b.[2014_Gross_Value]
    FROM Products AS p

LEFT JOIN 
     (SELECT p.PK_Product_ID AS Product_ID, COUNT(o.PK_Order_ID) AS 2013_Orders,  
     SUM((p.UnitPrice*od.Quantity)) AS 2013_Gross_Value
     FROM [Order Details] AS od, p, Orders AS o
     WHERE od.FK_Product_ID = p.PK_Product_ID
     AND od.FK_Order_ID = o.PK_Order_ID
     AND YEAR(o.OrderDate) = 2013
     GROUP BY p.PK_Product_ID) AS a

ON p.PK_Product_ID = a.Product_ID

LEFT JOIN 
    (SELECT p.PK_Product_ID AS Product_ID, COUNT(o.PK_Order_ID) AS 2014_Orders,  SUM((p.UnitPrice*od.Quantity)) AS 2014_Gross_Value
    FROM od, p, o
    WHERE od.FK_Product_ID = p.PK_Product_ID
    AND od.FK_Order_ID = o.PK_Order_ID
    AND YEAR(o.OrderDate) = 2014
    GROUP BY p.PK_Product_ID) AS b
 ON p.PK_Product_ID = b.Product_ID;

Solution

  • You can do it with conditional aggregation:

    SELECT p.PK_Product_ID AS Product_ID,
           SUM(IIF(YEAR(o.OrderDate) = 2013, 1, 0)) AS 2013_Orders,
           SUM(IIF(YEAR(o.OrderDate) = 2013, p.UnitPrice * od.Quantity, 0)) AS 2013_Gross_Value,
           SUM(IIF(YEAR(o.OrderDate) = 2014, 1, 0)) AS 2014_Orders,
           SUM(IIF(YEAR(o.OrderDate) = 2014, p.UnitPrice * od.Quantity, 0)) AS 2014_Gross_Value
    FROM (Products AS p LEFT JOIN [Order Details] AS od ON od.FK_Product_ID = p.PK_Product_ID)
    LEFT JOIN (SELECT * FROM Orders WHERE YEAR(OrderDate) IN (2013, 2014)) AS o ON od.FK_Order_ID = o.PK_Order_ID
    GROUP BY p.PK_Product_ID
    

    If you want only the products ordered in the years 2013 and/or 2014 then you can change the LEFT joins to INNER joins.