SQL Server 是执行内部联接还是交叉联接以根据另一个表中提供的日期范围进行扩展?

1szpjjfi  于 2022-12-17  发布在  其他
关注(0)|答案(1)|浏览(86)

我有两张table。
DateTable1(客户端的月份开始和结束日期,适当的月份编号):客户|月数|月份开始日期|月结束日期
DateTable2(对于每个客户端,每天占1行,该行包含适当的季度号):客户|日期|季度编号
我想创建一个日期表,使它每天有一行,为每个客户机显示QuarterNumber(到目前为止,它与DateTable2相同),另外我想从DateTable1中获得MonthNumber。
我正在考虑两种解决方案:
1.对客户端名称执行内部联接,并应用where条件进行筛选,以使DateTable2的日期介于DateTable1的开始值和结束值之间。
1.执行交叉连接(所以没有on子句),并应用与上面相同的where条件。
请您指导我如何从上述解决方案中进行选择?

46scxncf

46scxncf1#

这里的正确答案可能是利用日历表。
如果你不能或者不想完全实现一个,你可以用一点递归来伪造一个:

DECLARE @DateTable1 TABLE (Client INT, MonthNumber INT, MonthStartDate DATE, MonthEndDate DATE);
INSERT INTO @DateTable1 (Client, MonthNumber, MonthStartDate, MonthEndDate) VALUES
(1, 1, '2022-01-01', '2022-01-31'),(1, 2, '2022-02-01', '2022-02-28'),(1, 3, '2022-03-01', '2022-03-31'),(1, 4, '2022-04-01', '2022-04-30'),(1, 5, '2022-05-01', '2022-05-31'),
(2, 1, '2022-01-01', '2022-01-31'),(2, 2, '2022-02-01', '2022-02-28'),(2, 3, '2022-03-01', '2022-03-31'),(2, 4, '2022-04-01', '2022-04-30'),                            
(3, 1, '2022-01-01', '2022-01-31'),(3, 2, '2022-02-01', '2022-02-28'),(3, 3, '2022-03-01', '2022-03-31'),(3, 4, '2022-04-01', '2022-04-30'),(3, 5, '2022-05-01', '2022-05-31'),(3, 6, '2022-06-01', '2022-06-30');

;WITH cte AS (
SELECT Client, MIN(MonthNumber) AS mnS, MAX(MonthNumber) AS mnE, MIN(MonthStartDate) AS Date, DATEPART(QUARTER,MIN(MonthStartDate)) AS Quarter
  FROM @DateTable1
 GROUP BY Client
UNION ALL
SELECT Client, mnS, mnE, DATEADD(DAY,1,Date) AS Date, DATEPART(QUARTER,DATEADD(DAY,1,Date)) AS Quarter 
  FROM cte
 WHERE DATEPART(MONTH,DATEADD(DAY,1,Date)) <= mnE
)

SELECT Client, Date, Quarter
  FROM cte
 ORDER BY Client, Date
OPTION (MAXRECURSION 0)

仅使用其中一个表,我们就可以迭代应该提供给客户的日期,并填补空白。

Client  Date        Quarter
---------------------------
1       2022-01-01  1
1       2022-01-02  1
1       2022-01-03  1
...
1       2022-05-30  2
1       2022-05-31  2
2       2022-01-01  1
2       2022-01-02  1
...
2       2022-04-29  2
2       2022-04-30  2
3       2022-01-01  1
3       2022-01-02  1
...
3       2022-06-29  2
3       2022-06-30  2

现在,每个客户机每天都有一行(它们在第一个表中有数据),您可以根据需要加入该行。
编辑:
如果另一个表如所述,并且包含非标准季度编号,您可以直接加入它:

DECLARE @DateTable1 TABLE (Client INT, MonthNumber INT, MonthStartDate DATE, MonthEndDate DATE);
INSERT INTO @DateTable1 (Client, MonthNumber, MonthStartDate, MonthEndDate) VALUES
(1, 1, '2022-01-01', '2022-01-31'),(1, 2, '2022-02-01', '2022-02-28'),(1, 3, '2022-03-01', '2022-03-31'),(1, 4, '2022-04-01', '2022-04-30'),(1, 5, '2022-05-01', '2022-05-31'),
(2, 1, '2022-01-01', '2022-01-31'),(2, 2, '2022-02-01', '2022-02-28'),(2, 3, '2022-03-01', '2022-03-31'),(2, 4, '2022-04-01', '2022-04-30'),                            
(3, 1, '2022-01-01', '2022-01-31'),(3, 2, '2022-02-01', '2022-02-28'),(3, 3, '2022-03-01', '2022-03-31'),(3, 4, '2022-04-01', '2022-04-30'),(3, 5, '2022-05-01', '2022-05-31'),(3, 6, '2022-06-01', '2022-06-30');

DECLARE @DataTable2 TABLE (Client INT, Date DATE, QuarterNumber INT)
INSERT INTO @DataTable2 (Client, Date, QuarterNumber) VALUES

(1, '2022-01-01', 1),(1, '2022-01-02', 1),(1, '2022-01-03', 1),(1, '2022-01-04', 1),
(1, '2022-05-30', 2),(1, '2022-05-31', 2),(2, '2022-01-01', 1),(2, '2022-01-02', 1),
(2, '2022-01-03', 1),(2, '2022-04-29', 2),(2, '2022-04-30', 2),(3, '2022-01-01', 3),
(3, '2022-01-02', 3),(3, '2022-01-03', 3),(3, '2022-06-28', 4),(3, '2022-06-29', 4),
(3, '2022-06-30', 4)

;WITH cte AS (
SELECT Client, MIN(MonthNumber) AS mnS, MAX(MonthNumber) AS mnE, MIN(MonthStartDate) AS Date, DATEPART(QUARTER,MIN(MonthStartDate)) AS Quarter
  FROM @DateTable1
 GROUP BY Client
UNION ALL
SELECT Client, mnS, mnE, DATEADD(DAY,1,Date) AS Date, DATEPART(QUARTER,DATEADD(DAY,1,Date)) AS Quarter 
  FROM cte
 WHERE DATEPART(MONTH,DATEADD(DAY,1,Date)) <= mnE
)

SELECT c.Client, c.Date, d.QuarterNumber
  FROM cte c
    LEFT OUTER JOIN @DataTable2 d
      ON c.Client = d.Client
      AND c.Date = d.Date
 ORDER BY Client, Date
OPTION (MAXRECURSION 0)

我没有把另一张table上的每一个日期都包括进去。

相关问题