这应该让您对如何获得这些总数有一个很好的了解。我不知道您在表中还需要哪些其他数据,但您应该能够修改以下查询以获取它。
SQL小提琴
MS SQL Server 2017 架构设置:
/********************************CALENDAR********************************/
/*
My original answer made use of a Calendar Table, but I realized it
was overkill for this situation. I still think every database should
have both a Calendar Table and a Numbers Table. They are both very
useful. I use the ct here just to populate my test table, but I've
left some very basic creation to show you how it can be done. Calcs
done here allow your final query to JOIN to it and avoid RBAR to be
more set-based, and save a lot of processing for large tables.
NOTE: This original date table concept is from Aaron Bertrand.
*/
CREATE TABLE datedim (
theDate date PRIMARY KEY
, theDay AS DATEPART(day, theDate) --int
, theWeek AS DATEPART(week, theDate) --int
, theMonth AS DATEPART(month, theDate) --int
, theYear AS DATEPART(year, theDate) --int
, yyyymmdd AS CONVERT(char(8), theDate, 112) /* yyyymmdd */
);
/************************************************************************/
/*
Use the catalog views to generate as many rows as we need. This example
creates a date dimension for all of 2018.
*/
INSERT INTO datedim ( theDate )
SELECT d
FROM (
SELECT d = DATEADD(day, rn - 1, '20180101')
FROM
(
SELECT TOP (DATEDIFF(day, '20180101', '20190101'))
rn = ROW_NUMBER() OVER (ORDER BY s1.object_id)
FROM sys.all_objects AS s1
CROSS JOIN sys.all_objects AS s2
ORDER BY s1.object_id
) AS x
) AS y;
/************************************************************************/
/***** TEST TABLE SETUP *****/
CREATE TABLE t1 ( id int identity, entryDate date, cnt int) ;
INSERT INTO t1 (entryDate, cnt)
SELECT theDate, 2
FROM datedim
;
/* Remove a few "random" records to test our counts. */
DELETE FROM t1
WHERE datePart(day,entryDate) IN (10,6,14,22) OR datepart(month,entryDate) = 6
;
主要查询:
/* Make sure the first day or our week is consistent. */
SET DATEFIRST 7 ; /* SUNDAY */
/* Then build out our query needs with CTEs. */
; WITH theDate AS (
SELECT d.dt FROM ( VALUES ( '2018-05-17' ) ) d(dt)
)
, base AS (
SELECT t1.entryDate
, t1.cnt
, theDate.dt
, datepart(year,theDate.dt) AS theYear
, datepart(month,theDate.dt) AS theMonth
, datepart(week,theDate.dt) AS theWeek
FROM t1
CROSS APPLY theDate
WHERE t1.EntryDate <= theDate.dt
AND datePart(year,t1.EntryDate) = datePart(year,theDate.dt)
)
/* Year-to-date totals */
, ytd AS (
SELECT b.theYear, sum(cnt) AS s
FROM base b
GROUP BY b.theYear
)
/* Month-to-date totals */
, mtd AS (
SELECT b2.theYear, b2.theMonth, sum(cnt) AS s
FROM base b2
WHERE b2.theMonth = datePart(month,b2.EntryDate)
GROUP BY b2.theYear, b2.theMonth
)
/* Week-to-date totals */
, wtd AS (
SELECT b3.theYear, b3.theMonth, sum(cnt) AS s
FROM base b3
WHERE b3.theWeek = datePart(week,b3.EntryDate)
GROUP BY b3.theYear, b3.theMonth
)
SELECT blah = 'CountRow'
, ytd.s AS ytdAmt
, mtd.s AS mtdAmt
, wtd.s AS wtdAmt
FROM ytd
CROSS APPLY mtd
CROSS APPLY wtd
结果:
| blah | ytdAmt | mtdAmt | wtdAmt |
|----------|--------|--------|--------|
| CountRow | 236 | 28 | 8 |
同样,您需要获取的数据可能会改变整个查询,但这应该指向正确的方向。您可以使用每个 CTE 来验证 YTD、MTD 和 WTD 总计。