我在Microsoft T-SQL中有一个表“tblSalesOrder”,带有一些示例记录:
SalesOrderID OrderDate ItemID Quantity PromotionCode
====================================================================
1 2014-09-01 100 5 NULL
2 2014-09-01 120 10 ABC
3 2014-09-05 150 7 NULL
4 2014-09-08 200 15 NULL
我需要为不存在的记录返回NULL友好的结果集。
例如,我想要查看2014年9月的每月查询:
SELECT SalesOrderID, OrderDate, ItemID, Quantity, PromotionCode
FROM tblSalesOrder
WHERE OrderDate = BETWEEN '2014-09-01' AND '2014-09-30'
我需要它每天至少返回1行(如果当天的条目不可用,则为0值行)
SalesOrderID OrderDate ItemID Quantity PromotionCode
====================================================================
1 2014-09-01 100 5 NULL
2 2014-09-01 120 10 ABC
0 2014-09-02 0 0 0
0 2014-09-03 0 0 0
0 2014-09-04 0 0 0
3 2014-09-05 150 7 NULL
0 2014-09-06 0 0 0
0 2014-09-07 0 0 0
4 2014-09-08 200 15 NULL
0 2014-09-09 0 0 0
...
...
...
0 2014-09-30 0 0 0
答案 0 :(得分:2)
master..spt_values是包含2506行的所有microsoft sql数据库中的表,通过交叉连接,它将有2506 * 2506行来计算from和to之间的日期。也可以使用其他表,这只是用于创建日期的表。日历表甚至更容易使用。
EXCEPT将删除所有已使用的日期。然后通过将来自tblSalesOrder和CTE的行与union all组合在一起,空日将填充所需的硬编码值:
DECLARE @from date = '2014-09-01'
DECLARE @to date = '2014-09-30'
;WITH CTE as
(
SELECT top (case when @to < @from then 0 else datediff(day, @from, @to) + 1 end)
dateadd(day, row_number() over (order by (select 1)) - 1, @from) OrderDate
FROM
master..spt_values t1
CROSS JOIN
master..spt_values t2
EXCEPT
SELECT
OrderDate
FROM
tblSalesOrder
)
SELECT
0 SalesOrderID, OrderDate, 0 ItemID, 0 Quantity, '0' PromotionCode
FROM
CTE
UNION ALL
SELECT
SalesOrderID, OrderDate, ItemID, Quantity, PromotionCode
FROM
tblSalesOrder
ORDER BY
OrderDate, SalesOrderId
答案 1 :(得分:1)
您可以join
空select
和coalesce
中的日期参数:
select coalesce(t.SalesOrderID, 0) SalesOrderID
, coalesce(t.OrderDate, d.OrderDate) OrderDate
, coalesce(t.ItemID, 0) ItemID
, coalesce(t.Quantity, 0) Quantity
, coalesce(t.PromotionCode, 0) PromotionCode
from (select @dateParameter OrderDate) d
left
outer
join ( SELECT SalesOrderID, OrderDate, ItemID, Quantity, PromotionCode
FROM tblSalesOrder
) t
on t.OrderDate = d.OrderDate
答案 2 :(得分:1)
DECLARE @startDate date= '20140901'
,@endDate date = '20140930';
WITH Calendar as (
SELECT @startDate as OrderDate
UNION ALL
SELECT DATEADD(DAY, 1, OrderDate) as OrderDate
FROM Calendar
WHERE OrderDate < @endDate
)
SELECT coalesce(t.SalesOrderID, 0) SalesOrderID
, coalesce(t.OrderDate, Calendar.OrderDate) OrderDate
, coalesce(t.ItemID, 0) ItemID
, coalesce(t.Quantity, 0) Quantity
, CASE WHEN t.OrderDate IS NULL THEN '0' ELSE t.PromotionCode END as PromotionCode FROM Calendar
LEFT JOIN tblSalesOrder t ON Calendar.OrderDate = t.OrderDate
ORDER BY Calendar.OrderDate, t.SalesOrderID
OPTION (MAXRECURSION 0);