【问题标题】:How do I create dynamic column names in a WHILE DATE Loop query?如何在 WHILE DATE 循环查询中创建动态列名?
【发布时间】:2024-01-21 18:10:01
【问题描述】:

这是我的工作查询:

DECLARE @StartDate AS DATETIME
DECLARE @EndDate AS DATETIME
DECLARE @CurrentDate AS DATETIME

SET @StartDate = '2021-01-01'
SET @EndDate = GETDATE()
SET @CurrentDate = @StartDate

WHILE (@CurrentDate < @EndDate)
    BEGIN

        SELECT
        SUM(CASE WHEN [CreatedDateTime] BETWEEN @CurrentDate AND @CurrentDate + 6 THEN 1 ELSE 0 END)

        FROM Table
        WHERE OwnedBy = 'Service Desk'
        
        SET @CurrentDate = convert(varchar(30), dateadd(day,6, @CurrentDate), 101);
        
    END

产生以下结果:

我正在尝试创建一个显示每个结果的日期范围的动态列名。

例如:
第一个结果的列名应为:“Jan 1-Jan 7”
第二个结果应该有列名:“Jan 8-Jan 14”
等等

有没有办法做到这一点?

谢谢。

【问题讨论】:

  • 根据问题指南,请不要发布代码、数据、错误消息等的图像 - 将文本复制或输入到问题中。请保留将图像用于图表或演示渲染错误,无法通过文本准确描述的事情。
  • 对于动态列名,您需要动态 SQL。为什么不在你的前端这样做呢?容易得多。

标签: sql-server date tsql while-loop


【解决方案1】:

这是解决此类数据库问题的一种非常不寻常的方法。您可以改为考虑使用两列,无循环,如下所示:

DECLARE @StartDate AS DATETIME = '20210101';
WITH e1(n) AS
(
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
)-- 10*1
,e2(n) AS (SELECT 1 FROM e1 CROSS JOIN e1 AS b) -- 10*10
,e3(n) AS (SELECT 1 FROM e1 CROSS JOIN e2) -- 10*100
,Dates as (
    SELECT DATEADD(d, ROW_NUMBER() over (ORDER BY n)-1, @StartDate) AS BaseDate 
    FROM e3 
)
SELECT d.BaseDate As PeriodStart -- datetime value
    , FORMAT(d.BaseDate, 'MMM dd')+ '-' + FORMAT(DATEADD(d, 6, d.BaseDate), 'MMM dd') as PeriodRange -- string value
    , COUNT(t.*) As TicketCount
FROM Dates d
INNER JOIN [Table] t ON t.[CreatedDateTime] >= d.BaseDate 
    AND t.[CreatedDateTime] < DATEADD(d, 7, d.BaseDate)
    AND t.OwnedBy='Service Desk'
WHERE d.BaseDate < CURRENT_TIMESTAMP
GROUP BY d.BaseDate;

这可能会快很多倍,并且通常更容易在客户端代码和报告工具中使用。

这里的另一个值得注意的变化是,我使用了两个单独的条件,而不是未来六天的 BETWEEN 表达式,其中结束条件是 独占上限 7 天未来,这通常也是处理日期范围的更好方法。

【讨论】: