这是数据:
SELECT X.*
INTO #X
FROM (
VALUES
('A',CAST('01 Feb 2013' AS DATETIME)),
('B','01 Mar 2013'),
('C','01 Sep 2013')
) X(Player,Mth)
我们的仓库里有一个非常标准的工厂DimDate
表。
如果我执行以下操作以查找工作正常的天数:
SELECT Player,Mth,
numDays_mth = COUNT(XXX.DateKey),
FROM #X A
CROSS APPLY
(
SELECT DateKey
FROM WHData.dbo.vw_DimDate DT
WHERE DT.DayMarker >= A.Mth
AND DT.DayMarker < DATEADD(MONTH, 1, A.Mth)
) XXX
同样,从上个月开始的工作天数很好:
SELECT Player,Mth,
numDays_prevMth = COUNT(YYY.DateKey)
FROM #X A
CROSS APPLY
(
SELECT DateKey
FROM WHData.dbo.vw_DimDate DTT
WHERE DTT.DayMarker >= DATEADD(MONTH, -1, A.Mth)
AND DTT.DayMarker < A.Mth
) YYY
如果我把两者结合起来就会出现问题:
SELECT Player,Mth,
numDays_mth = COUNT(XXX.DateKey),
numDays_prevMth = COUNT(YYY.DateKey)
FROM #X A
CROSS APPLY
(
SELECT DateKey
FROM WHData.dbo.vw_DimDate DT
WHERE DT.DayMarker >= A.Mth
AND DT.DayMarker < DATEADD(MONTH, 1, A.Mth)
) XXX
CROSS APPLY
(
SELECT DateKey
FROM WHData.dbo.vw_DimDate DTT
WHERE DTT.DayMarker >= DATEADD(MONTH, -1, A.Mth)
AND DTT.DayMarker < A.Mth
) YYY
我意识到还有很多其他方法可以实现这些日计算,但我正在努力了解APPLY
运算符的运作方式。
如何继续使用APPLY
两次并停止重复数据?
注意
将SELECT
子句更改为以下内容可以解决这个简单的示例,但会对生产脚本的性能产生巨大影响:
SELECT Player,Mth,
numDays_mth = COUNT(DISTINCT XXX.DateKey),
numDays_prevMth = COUNT(DISTINCT YYY.DateKey)
答案 0 :(得分:2)
我会移动COUNT
内的CROSS APPLY
,以便每个只为left hand side上的每个输入行生成一行输出。这样您就可以避免创建其他行来充当第二个(或后续)APPLY
的输入:
SELECT Player,Mth,
numDays_mth = XXX.Cnt,
numDays_prevMth = YYY.Cnt
FROM #X A
CROSS APPLY
(
SELECT COUNT(DateKey)
FROM WHData.dbo.vw_DimDate DT
WHERE DT.DayMarker >= A.Mth
AND DT.DayMarker < DATEADD(MONTH, 1, A.Mth)
) XXX (Cnt)
CROSS APPLY
(
SELECT COUNT(DateKey)
FROM WHData.dbo.vw_DimDate DTT
WHERE DTT.DayMarker >= DATEADD(MONTH, -1, A.Mth)
AND DTT.DayMarker < A.Mth
) YYY (Cnt)