use*_*307 3 sql t-sql join left-join sql-server-2008-r2
我有两张桌子.
与客户和日期的订单表.数据仓库中的日期维度表.
订单表不包含给定月份中每个日期的活动,但我需要返回填充日期和客户的差距的结果集.
例如,我需要这个:
Customer Date =============================== Cust1 1/15/2012 Cust1 1/18/2012 Cust2 1/5/2012 Cust2 1/8/2012
看起来像这样:
Customer Date ============================ Cust1 1/15/2012 Cust1 1/16/2012 Cust1 1/17/2012 Cust1 1/18/2012 Cust2 1/5/2012 Cust2 1/6/2012 Cust2 1/7/2012 Cust2 1/8/2012
这似乎是左外连接,但它没有返回预期的结果.这是我正在使用的,但这并不是按预期返回日期表中的每个日期.
SELECT o.customer,
d.fulldate
FROM datetable d
LEFT OUTER JOIN orders o
ON d.fulldate = o.orderdate
WHERE d.calendaryear IN ( 2012 );
Run Code Online (Sandbox Code Playgroud)
问题是您需要所有日期的所有客户。执行 时left outer join
,客户字段为 NULL。
下面通过cross join
输入客户姓名和日期来设置驱动程序表:
SELECT driver.customer, driver.fulldate, o.amount
FROM (select d.fulldate, customer
from datetable d cross join
(select customer
from orders
where year(orderdate) in (2012)
) o
where d.calendaryear IN ( 2012 )
) driver LEFT OUTER JOIN
orders o
ON driver.fulldate = o.orderdate and
driver.customer = o.customer;
Run Code Online (Sandbox Code Playgroud)
请注意,此版本假定calendaryear
与year(orderdate)
.
您可以使用递归CTE获取两个日期之间的所有日期,而无需datetable
:
;WITH CTE_MinMax AS
(
SELECT Customer, MIN(DATE) AS MinDate, MAX(DATE) AS MaxDate
FROM dbo.orders
GROUP BY Customer
)
,CTE_Dates AS
(
SELECT Customer, MinDate AS Date
FROM CTE_MinMax
UNION ALL
SELECT c.Customer, DATEADD(DD,1,Date) FROM CTE_Dates c
INNER JOIN CTE_MinMax mm ON c.Customer = mm.Customer
WHERE DATEADD(DD,1,Date) <= mm.MaxDate
)
SELECT c.* , COALESCE(o.Amount, 0)
FROM CTE_Dates c
LEFT JOIN Orders o ON c.Customer = o.Customer AND c.Date = o.Date
ORDER BY Customer, Date
OPTION (MAXRECURSION 0)
Run Code Online (Sandbox Code Playgroud)