简体   繁体   中英

Using SQL join to retrieve set of data for each different value in a column

I am working on retrieving data from two SQL tables on SQL Server in which I am trying to get all rows from right table for each distinct value in a column in left table no matter if there is a match or not

For example I have two tables named products and Deals with following data

Products table

Id Product
1  ABC
2  XYZ
3  PQR

Deals Table

Id  TradeDate  Product Volume   Price    Delivery
56  2014-12-08  ABC     2500    -3.25   2015-01-01 
57  2014-12-08  ABC     2500    -3.4    2015-02-01 
63  2014-12-08  PQR     2500    -7      2015-01-01 
64  2014-12-08  PQR     2500    -7      2015-01-01 

I applied following query to the above tables

SELECT
         FORMAT(a.Delivery,'MMMM yyyy') AS Delivery,

         b.Product,COUNT(a.Id) AS Trades, 
         ROUND(((6.2898*SUM(a.Volume ))/DAY(EOMONTH(DATEADD(MONTH, DATEDIFF(MONTH, 0,a.Delivery), 0))))*0.001,4) AS BBLperDay,
         SUM(a.Volume) AS M3,       
         ROUND(SUM(a.Volume*a.Price)/Sum(a.Volume),4) AS WeightedAverage
FROM     Deals AS a right outer join Products AS b 
         ON a.Product=b.Product 
         AND CAST(a.TradeDate as date)='2014-12-08' 
GROUP BY b.Product,CAST(a.TradeDate as date), 
         DATEADD(MONTH, DATEDIFF(MONTH, 0,a.Delivery),0),  FORMAT(a.Delivery,'MMMM yyyy')

And I got following results

 Delivery     Product    Trades  BBLperDay   M3  WeightedAverage
 January 2015   ABC         1   0.5072      2500      -3.25
 February 2015  ABC         1   0.5616      2500      -3.4
 January 2015   PQR         2   1.0145      5000        -7
 (null)         XYZ         0   (null)      (null)      (null)

The above results are expected for the query but I am trying a way to get the results such that from the above results I want all rows in Products table for each distinct Delivery value by making Delivery value as default for every equivalent result and other fields be NULL as follows

 Delivery     Product    Trades  BBLperDay   M3  WeightedAverage
  January 2015   ABC        1   0.5072      2500      -3.25
  January 2015   PQR        2   1.0145      5000        -7
  January 2015   XYZ        0   (null)      (null)      (null)
  February 2015  ABC        1   0.5616      2500      -3.4
  February 2015  XYZ        0   (null)      (null)      (null)
  February 2015  PQR        0   (null)      (null)      (null)

The above results can be explained as from actual results I have January 2015 Delivery for products ABC and PQR but the Products table as one more product XYZ which is missing for January 2015, so I added XYZ for January 2015 with Delivery as January 2015 and remaining NULL. Same is the case with February 2015 Delivery it has only ABC so I added products XYZ and PQR to the results.

Please refer to http://sqlfiddle.com/#!6/db1508/3

May I know a good way to get this data?

I'd just build out that 'backbone' of delivery products first and put your original query against it with a left join. Shown here with CTEs.

WITH deliveryProducts AS
(
     SELECT DISTINCT FORMAT(a.Delivery,'MMMM yyyy') AS Delivery, b.Product 
     FROM DEALS as a, PRODUCTS as b Where CAST(a.TradeDate as date)='2014-12-08'
)
, deliveryActuals AS
(
     SELECT
           FORMAT(a.Delivery,'MMMM yyyy') AS Delivery,

           b.Product,ISNULL(COUNT(a.Id),0) AS Trades, 
           ROUND(((6.2898*SUM(a.Volume ))/DAY(EOMONTH(DATEADD(MONTH, DATEDIFF(MONTH, 0,a.Delivery), 0))))*0.001,4) AS BBLperDay,
           SUM(a.Volume) AS M3,       
           ROUND(SUM(a.Volume*a.Price)/Sum(a.Volume),4) AS WeightedAverage

     FROM
           Deals AS a right outer join Products AS b 
           ON a.Product=b.Product 
           AND CAST(a.TradeDate as date)='2014-12-08'

     GROUP BY
           b.Product,CAST(a.TradeDate as date), 
           DATEADD(MONTH, DATEDIFF(MONTH, 0,a.Delivery),0),  FORMAT(a.Delivery,'MMMM yyyy')
)

SELECT
     dp.Delivery, dp.Product, trades, BBLperDay, M3, WeightedAverage
FROM
     deliveryProducts dp

LEFT JOIN deliveryActuals da
     on dp.Delivery = da.Delivery
     and dp.product = da.Product

ORDER BY dp.Delivery

Here it is in your SQLFiddle

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM