我有一个问题,我无法理解。
我有一个事件表和一个用户表。有些活动是收费的,有些则不是。我想要确定的是每个用户每周每月的收费天数。
这是数据......
ID FromDate ToDate isChargeable Username
1 2014-11-03 2014-11-04 Y AUser
2 2014-11-04 2014-11-06 Y AUser
3 2014-11-07 2014-11-07 Y AUser
我已经编写了一个基本查询来计算from和to日期之间的差异,并将它们加总为1,因为toDate计算为一整天。
SELECT DISTINCT FromDate, ToDate, isChargeable,Username, DATEDIFF(day, FromDate, ToDate) + 1) AS 'count1'
FROM dbo.vDiary
GROUP BY FromDate, ToDate, isChargeable,Username
这导致......
FromDate ToDate isChargeable Username count1
2014-11-03 2014-11-04 Y AUser 2
2014-11-04 2014-11-06 Y AUser 3
2014-11-07 2014-11-07 Y AUser 1
这是不正确的,因为它显示了6个工作日,因为两个事件重叠。
如何允许这种重叠?我需要声明,如果某一天的某个活动是收费的,那么这一天是收费日。
我想我需要一张日历表,但我不确定使用它来获得正确的结果。
任何帮助都会非常感激!!
由于
史蒂夫
编辑:从下面尝试解决方案
;WITH cte
AS (SELECT Row_number()OVER(PARTITION BY Username ORDER BY FromDate) rn,
FromDate,ToDate,isChargeable,Username
FROM #calen)
SELECT a.FromDate,a.ToDate,a.isChargeable,a.Username,
CASE
WHEN a.FromDate > b.ToDate
OR b.ToDate IS NULL THEN Datediff(day, a.FromDate, a.ToDate) + 1
ELSE Datediff(day, Dateadd(dd, 1, b.ToDate), a.ToDate)+ 1
END DatDiff,
*
FROM cte a
LEFT JOIN cte b
ON a.rn = b.rn + 1
AND a.username = b.username
WHERE ( a.ToDate > b.todate
OR b.ToDate IS NULL )
制作(更新)
FromDate ToDate isChargeable Username DatDiff rn FromDate ToDate isChargeable Username rn FromDate ToDate isChargeable Username
2014-11-03 2014-11-04 Y AUser 2 1 2014-11-03 2014-11-04 Y AUser NULL NULL NULL NULL NULL
2014-11-04 2014-11-06 Y AUser 2 2 2014-11-04 2014-11-06 Y AUser 1 2014-11-03 2014-11-04 Y AUser
2014-11-07 2014-11-07 Y AUser 1 3 2014-11-07 2014-11-07 Y AUser 2 2014-11-04 2014-11-06 Y AUser
2014-12-03 2014-12-15 Y AUser 13 4 2014-12-03 2014-12-15 Y AUser 3 2014-11-07 2014-11-07 Y AUser
2014-12-10 2014-12-17 Y AUser 2 5 2014-12-10 2014-12-17 Y AUser 4 2014-12-03 2014-12-15 Y AUser
2015-12-04 2015-12-15 Y AUser 12 6 2015-12-04 2015-12-15 Y AUser 5 2014-12-10 2014-12-17 Y AUser
2014-11-03 2014-11-03 Y BUser 1 1 2014-11-03 2014-11-03 Y BUser NULL NULL NULL NULL NULL
2014-11-04 2014-11-04 Y BUser 1 2 2014-11-04 2014-11-04 Y BUser 1 2014-11-03 2014-11-03 Y BUser
答案 0 :(得分:1)
试试这个。
如果您有唯一ID,请尝试此操作。
create table #calen(ID int, FromDate date, ToDate date,isChargeable char(1),Username varchar(20))
INSERT #calen
VALUES (1,'2014-11-03','2014-11-04','Y ','AUser'),
(2,'2014-11-04','2014-11-06','Y','AUser'),
(3,'2014-11-07','2014-11-07','Y','AUser')
SELECT a.FromDate,a.ToDate,a.isChargeable,a.Username,
CASE
WHEN a.FromDate > b.ToDate
OR b.ToDate IS NULL THEN Datediff(day, a.FromDate, a.ToDate) + 1
ELSE Datediff(day, Dateadd(dd, 1, b.ToDate), a.ToDate)
+ 1
END DatDiff
FROM #calen a
LEFT JOIN #calen b
ON a.id = b.id + 1
WHERE ( a.ToDate > b.todate
OR b.ToDate IS NULL )
更新:
对于多个用户。
;WITH cte
AS (SELECT Row_number()OVER(PARTITION BY Username ORDER BY FromDate) rn,
FromDate,ToDate,isChargeable,Username
FROM #calen)
SELECT a.FromDate,a.ToDate,a.isChargeable,a.Username,
CASE
WHEN a.FromDate > b.ToDate
OR b.ToDate IS NULL THEN Datediff(day, a.FromDate, a.ToDate) + 1
ELSE Datediff(day, Dateadd(dd, 1, b.ToDate), a.ToDate)+ 1
END DatDiff
FROM cte a
LEFT JOIN cte b
ON a.rn = b.rn + 1
AND a.username = b.username
WHERE ( a.ToDate > b.todate
OR b.ToDate IS NULL )
输出:
FromDate ToDate isChargeable Username DatDiff
---------- ---------- ------------ -------- -------
2014-11-03 2014-11-04 Y AUser 2
2014-11-04 2014-11-06 Y AUser 2
2014-11-07 2014-11-07 Y AUser 1
答案 1 :(得分:1)
如果所有ID值都不唯一,我们可以使用以下查询:
SELECT ID, FromDate, ToDate, isChargeable, Username,
CASE WHEN EXISTS(SELECT ToDate FROM UserTable B WHERE A.FromDate = B.ToDate
AND A.UserName = B.UserName AND A.ID <> B.ID) THEN
DATEDIFF(day, FromDate, ToDate)
ELSE
DATEDIFF(day, FromDate, ToDate) + 1
END AS 'count1'
FROM UserTable A
否则我们必须创建CTE以创建唯一的ROWID。
;WITH UserTable
AS (SELECT Row_number() OVER(ORDER BY FromDate) RowID,
FromDate,ToDate, isChargeable, Username
FROM #user)
SELECT RowID, FromDate, ToDate, isChargeable, Username,
CASE WHEN EXISTS(SELECT ToDate FROM UserTable B WHERE A.FromDate = B.ToDate
AND A.UserName = B.UserName AND A.RowID <> B.RowID) THEN
DATEDIFF(day, FromDate, ToDate)
ELSE
DATEDIFF(day, FromDate, ToDate) + 1
END AS 'count1'
FROM UserTable A
答案 2 :(得分:1)
试试这个:
WITH CTE AS
(SELECT a.* ,y.flag
FROM EventsTable a
OUTER APPLY
(SELECT DATEDIFF(dd, a.ToDate, x.FromDate) as flag
FROM EventsTable x
WHERE a.id = x.id AND x.FromDate > a.ToDate) y)
SELECT id,FromDate,ToDate,isChargeable,Username,
CASE WHEN flag = 1 THEN
DATEDIFF(dd, FromDate, ToDate)
ELSE DATEDIFF(dd, FromDate,ToDate) + 1
END AS count1
FROM CTE