我有一张表格,我必须按天,按周和按月计算分配给每个用户的总行数。
表BooksIssued
BOOKID ISSUEDUSER DATE
1 A 20160708
2 A 20160709
3 A 20160708
4 A 20150102
5 B 20160709
6 C 20160708
7 C 20160708
现在我必须为每个用户发送COUNT每日,每周和每月的书籍
每日是今天(20160709) 每周是周日至周六 每月是整月
结果应为
ISSUEDUSER DAILYBOOKS WEEKLYBOOKS MONTHLYBOOKS
A 1 3 3
B 1 1 1
C 0 2 2
我已经为每日发布的
做了这个SQLSELECT ISSUEDUSER, COUNT(BOOKID) AS DAILYBOOKS
FROM BOOKSISSUED
WHERE DATE = CONVERT(VARCHAR(11), SYSDATETIME(), 112)
GROUP BY ISSUEDUSER
有人可以帮我写三个组合 SQL吗?
由于
艾登
答案 0 :(得分:3)
您可能需要添加WHERE子句以仅检索当前月份的记录
SELECT ISSUEDUSER,
SUM(CASE WHEN DATE = DATEADD(DAY, DATEDIFF(DAY, 0, SYSDATETIME()), 0))
THEN 1 ELSE 0 END) AS DAILYBOOKS,
SUM(CASE WHEN DATE >= DATEADD(WEEK, DATEDIFF(WEEK, 0, SYSDATETIME()), 0)
AND DATE < DATEADD(WEEK, DATEDIFF(WEEK, 0, SYSDATETIME()) + 1, 0)
THEN 1 ELSE 0 END) AS WEEKLYBOOKS,
COUNT(*) AS MONTHLYBOOKS
FROM BOOKSISSUED
WHERE DATE >= DATEADD(MONTH, DATEDIFF(MONTH, 0, SYSDATETIME()), 0)
AND DATE < DATEADD(MONTH, DATEDIFF(MONTH, 0, SYSDATETIME()) + 1, 0)
GROUP BY ISSUEDUSER
编辑:[日期]列为INT
SELECT ISSUEDUSER,
SUM(CASE WHEN DATE = CONVERT(INT, CONVERT(VARCHAR(8), SYSDATETIME(), 112))
THEN 1 ELSE 0 END) AS DAILYBOOKS,
SUM(CASE WHEN DATE >= CONVERT(INT, CONVERT(VARCHAR(8), DATEADD(WEEK, DATEDIFF(WEEK, 0, SYSDATETIME()), 0), 112))
AND DATE < CONVERT(INT, CONVERT(VARCHAR(8), DATEADD(WEEK, DATEDIFF(WEEK, 0, SYSDATETIME()) + 1, 0), 112))
THEN 1 ELSE 0 END) AS WEEKLYBOOKS,
COUNT(*) AS MONTHLYBOOKS
FROM BOOKSISSUED
WHERE DATE >= CONVERT(INT, CONVERT(VARCHAR(6), SYSDATETIME(), 112) + '01')
AND DATE < CONVERT(INT, CONVERT(VARCHAR(6), DATEADD(MONTH, 1, SYSDATETIME()), 112) + '01')
GROUP BY ISSUEDUSER
答案 1 :(得分:2)
它使得比较官方开始和结束的周更容易和实用。嘿,你甚至可以使用索引编制!
然而,还有另一种方式。如您所见,DATEPART
返回我们正在寻找的ISO月份和周。
所以如果我们的年份是正确的,我们现在知道我们的界限在哪里,并且可以在IIF(<boolean_expression>, <true_expression>, <false_expression>)
内轻松使用COUNT(<column>)
声明。 COUNT
忽略了NULL
,因此我们将TRUE
设置为1,将FALSE
设置为NULL
。 :d
-- Note, I changed the column [Date] to [Dates]
DECLARE @Date INT
SET @Date = CAST(CAST(SYSDATETIME() AS VARCHAR(4) ) + '0101' AS INT)
SELECT ISSUEDUSER--DATEPART(YYYY, CAST(Dates AS VARCHAR(10) ) )
, COUNT( IIF(DATEDIFF(MM, CAST(Dates AS VARCHAR(10) ), GETDATE() ) = 0
, 1
, NULL) ) AS MONTHS
, COUNT( IIF(DATEDIFF(WW, CAST(Dates AS VARCHAR(10) ), GETDATE() ) = 0
, 1
, NULL) ) AS Weeks
, COUNT( IIF(DATEDIFF(DD, CAST(Dates AS VARCHAR(10) ), GETDATE() ) = 0
, 1
, NULL) ) AS Days
FROM #BookReport
WHERE DATES >= @Date
GROUP BY ISSUEDUSER
--results
ISSUEDUSER MONTHS Weeks Days
A 3 3 1
B 1 1 1
C 2 2 0
请注意,您可以通过调整boolean
语句来扩展允许的日期差异!无需额外编码。
另请注意,您的示例实际上只有一个日期不是同一个月,周或日(在一天内),尽管在我的示例中我要求Days与查询的日期相同看起来有点不同。
DATE
根据定义没有格式,而DATEPART
可以从结构良好的Datetime
字符串进行猜测,因此没有理由对您的日期进行双重投射柱。但是,如果您的模式发生变化,则可能需要添加CONVERT
。DATEPART
为您提供标准(ISO)月和周识别,这意味着此处不需要Date_Time表。 :)DATEDIFF
在这里很神奇,让您的Boolean
语句非常容易使用。