如何在 SQL 服务器的查询中创建日期-table?

How can I create a dates-table inside a query in SQL Server?

假设我想将 table_a 中具有 startdateenddate 的记录与个别日期进行匹配,并查看是否在(例如 3 月 13 日) table_a 匹配。我想通过每天生成一行来解决这个问题,日期作为前导列,来自 table_a 的任何匹配数据作为 left join.

我曾使用过具有 date 维度的数据仓库,使这项工作变得容易。但不幸的是,我需要 运行 在没有 table.

的 OLTP 数据库上执行此特定查询

如何在 SQL 服务器中每天生成一行 table?在没有临时 tables、functions/procedures 等的情况下,如何在我的查询中执行此操作?

我找到了一些破解方法来执行此操作。我假设两年的约会对你来说已经足够 dates table.

现在,在您的数据库中找到一个至少有 800 条记录的 table(365 x 2 + 闰年 - 令人头疼的乘法 365 = ~~ 800)。该问题讨论的是从 table_a 中选择数据,因此我们假设这是 table_b。然后,在查询的顶部创建这个通用 Table 表达式:

with dates_table as (
    select top 800  -- or more/less if your timespan isn't ~2years
        [date] = date_add(day, ROW_NUMBER() over (order by <random column>) -1, <your-start-date>)
    from table_b
)

select d.[date]
, a.<whatever>
from dates_table d
left outer join table_a a on <join / date matching here>
-- where etc, etc, etc

一些注意事项:

  • 这只需获取数字 0 - 799 并将它们添加到任意日期即可。
  • 如果您需要多于或少于两年的日期,请增加或减少输入 top 语句的数字。确保 table_b 有足够的行:select count(*) from table_b.
  • <random column 可以是 table_b 上的任何列,顺序无关紧要。我们只对数字 1-800 感兴趣(-1 表示 0-799 的范围),但是 ROW_NUMBER 需要一个 order by 参数。
  • <your-start-date> 在日期 table 中有您想要的第一个日期,并包含在输出中。
  • 在连接查询的 where 中,您可以通过添加 year(d.[date]) IN (2020, 2021).[= 之类的内容来过滤掉我们超过的任何多余天数,方法是使用 800 行而不是 730 行(+leap) 39=]
  • 如果 table_a 本身有超过 800 条记录,这可以用作 dates_table 的基础,而不是其他一些 table。

另一种方法是使用递归查询来生成日期系列。根据您的 pseudo-code:

with dates_table as (
    select <your-start-date> dt
    union all
    select dateadd(day, 1, dt) from dates_table where dt < <your-end-date>
)
select d.dt, a.<whatever>
from dates_table d
left outer join table_a a on <join / date matching here>
-- where etc etc
option (maxrecursion 0)