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.