当前,我正在尝试将日期表联接到分类帐表,以便在某些情况下(例如3月1日和3月3日有交易,但没有交易记录)填补空白表的空白3月2日进行交易。通过将两个表连接起来,3月2日将出现在分类帐表中,但我们要分析的变量为0。)
挑战在于我无法创建Date对象/表/维度,因为我没有在数据库中创建表的权限。因此,我一直在使用以下代码生成日期序列:
DECLARE @startDate date = CAST('2016-01-01' AS date),
@endDate date = CAST(GETDATE() AS date);
SELECT DATEADD(day, number - 1, @startDate) AS [Date]
FROM (
SELECT ROW_NUMBER() OVER (
ORDER BY n.object_id
)
FROM sys.all_objects n
) S(number)
WHERE number <= DATEDIFF(day, @startDate, @endDate) + 1;
那么,是否有可能将两个表连接到同一条语句中?假设分类帐表如下所示:
SELECT
date,cost
FROM ledger
我认为可以通过使用子查询来完成,但是我不知道怎么做。
谢谢。
答案 0 :(得分:2)
Aaron Bertrand的一篇很好的文章介绍了几种在SQL Server中生成数字序列(或日期)的方法:Generate a set or sequence without loops – part 1。
尝试一下,看看自己更快或更方便。 (破坏者-递归CTE相当慢)
选择了首选方法后,可以将其包装在CTE(common-table expression)中。
在这里,我将使用问题中的方法
WITH
CTE_Dates
AS
(
SELECT
DATEADD(day, number - 1, @startDate) AS dt
FROM (
SELECT ROW_NUMBER() OVER (
ORDER BY n.object_id
)
FROM sys.all_objects n
) S(number)
WHERE number <= DATEDIFF(day, @startDate, @endDate) + 1
)
SELECT
...
FROM
CTE_Dates
LEFT JOIN Ledger ON Ledger.dt = CTE_Dates.dt
;
答案 1 :(得分:1)
您可以将生成的日期序列用作CTE,并将LEFT JOIN
用于ledger
表。例如:
DECLARE @startDate date = CAST('2020-02-01' AS date);
DECLARE @endDate date = CAST(GETDATE() AS date);
WITH dates AS (
SELECT DATEADD(day, number - 1, @startDate) AS [Date]
FROM (
SELECT ROW_NUMBER() OVER (
ORDER BY n.object_id
)
FROM sys.all_objects n
) S(number)
WHERE number <= DATEDIFF(day, @startDate, @endDate) + 1
)
SELECT dates.Date, COALESCE(ledger.cost, 0)
FROM dates
LEFT JOIN (VALUES ('2020-02-02', 14), ('2020-02-05', 10)) AS ledger([Date], [cost]) ON dates.Date = ledger.Date
输出:
Date cost
2020-02-01 0
2020-02-02 14
2020-02-03 0
2020-02-04 0
2020-02-05 10
2020-02-06 0