Count records by month starting with July to June - tsql

We use calendar months July - June instead of January - December. I have a query that counts each record by month and adds the previous month's records to the new month Jan to Fab. Is there a way to start with the month of July and add July's counts to August and August to October and so on...
Here is the query:
SELECT ReviewType,
COUNT(CASE WHEN MONTH(dateCompleted) <= 1 THEN ReviewType END) AS Jan,
COUNT(CASE WHEN MONTH(dateCompleted) <= 2 THEN ReviewType END) AS Feb,
COUNT(CASE WHEN MONTH(dateCompleted) <= 3 THEN ReviewType END) AS Mar,
COUNT(CASE WHEN MONTH(dateCompleted) <= 4 THEN ReviewType END) AS Apr,
COUNT(CASE WHEN MONTH(dateCompleted) <= 5 THEN ReviewType END) AS May,
COUNT(CASE WHEN MONTH(dateCompleted) <= 6 THEN ReviewType END) AS Jun,
COUNT(CASE WHEN MONTH(dateCompleted) <= 7 THEN ReviewType END) AS Jul,
COUNT(CASE WHEN MONTH(dateCompleted) <= 8 THEN ReviewType END) AS Aug,
COUNT(CASE WHEN MONTH(dateCompleted) <= 9 THEN ReviewType END) AS Sep,
COUNT(CASE WHEN MONTH(dateCompleted) <= 10 THEN ReviewType END) AS Oct,
COUNT(CASE WHEN MONTH(dateCompleted) <= 11 THEN ReviewType END) AS Nov,
COUNT(CASE WHEN MONTH(dateCompleted) <= 12 THEN ReviewType END) AS Dec,
COUNT(ReviewType) AS Result
FROM ALAN.dbo.qryPeakReviews
WHERE fiscalYear = 1819
GROUP BY ReviewType;
Here is the output:
ReviewType Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec Result
1 0 17 46 57 67 72 72 72 83 87 93 94 94
2 0 2 22 27 31 34 34 37 43 48 48 48 48
3 0 1 16 28 34 37 37 39 45 47 49 49 49

Add 6 to all the months and get the remainder of the division of the result with 12:
SELECT ReviewType,
COUNT(CASE WHEN (MONTH(dateCompleted) + 6) % 12 = 1 THEN ReviewType END) AS Jul,
COUNT(CASE WHEN (MONTH(dateCompleted) + 6) % 12 BETWEEN 1 AND 2 THEN ReviewType END) AS Aug,
COUNT(CASE WHEN (MONTH(dateCompleted) + 6) % 12 BETWEEN 1 AND 3 THEN ReviewType END) AS Sep,
COUNT(CASE WHEN (MONTH(dateCompleted) + 6) % 12 BETWEEN 1 AND 4 THEN ReviewType END) AS Oct,
COUNT(CASE WHEN (MONTH(dateCompleted) + 6) % 12 BETWEEN 1 AND 5 THEN ReviewType END) AS Nov,
COUNT(CASE WHEN (MONTH(dateCompleted) + 6) % 12 BETWEEN 1 AND 6 THEN ReviewType END) AS Dec,
COUNT(CASE WHEN (MONTH(dateCompleted) + 6) % 12 BETWEEN 1 AND 7 THEN ReviewType END) AS Jan,
COUNT(CASE WHEN (MONTH(dateCompleted) + 6) % 12 BETWEEN 1 AND 8 THEN ReviewType END) AS Feb,
COUNT(CASE WHEN (MONTH(dateCompleted) + 6) % 12 BETWEEN 1 AND 9 THEN ReviewType END) AS Mar,
COUNT(CASE WHEN (MONTH(dateCompleted) + 6) % 12 BETWEEN 1 AND 10 THEN ReviewType END) AS Apr,
COUNT(CASE WHEN (MONTH(dateCompleted) + 6) % 12 BETWEEN 1 AND 11 THEN ReviewType END) AS May,
COUNT(ReviewType) AS Jun,
COUNT(ReviewType) AS Result
FROM ALAN.dbo.qryPeakReviews
WHERE fiscalYear = 1819
GROUP BY ReviewType;
I changed the inequality check with BETWEEN 1 AND ... because June is calculated as 0 and should not be included.
Also there is no reason to count anything special for the last month June. It is the total of all the year.

Related

How to get count in same results including zero count values? (PostgreSQL)

Here is my problem...I have this query already giving me the results I am looking for except that I need to display rows that have zero values... in the column "station" I should be displaying numbers 4 and 7 too with zero values:
select
sum("Ch1") AS "Ch1",
sum("Ch2") AS "Ch2",
sum("Ch3") AS "Ch3",
sum("Ch4") AS "Ch4",
CASE WHEN "FailCode" >= 10 and "FailCode" <= 13 THEN 1
WHEN "FailCode" >= 14 and "FailCode" <= 17 THEN 2
WHEN "FailCode" >= 18 and "FailCode" <= 21 THEN 3
WHEN "FailCode" >= 23 and "FailCode" <= 26 THEN 4
WHEN "FailCode" >= 27 and "FailCode" <= 30 THEN 5
WHEN "FailCode" >= 35 and "FailCode" <= 38 THEN 6
WHEN "FailCode" >= 40 and "FailCode" <= 43 THEN 7
END AS station
from (
SELECT "FailCode",
count (*) FILTER (WHERE "FailCode" =10 or "FailCode"=14 or "FailCode"=18 or "FailCode"=23 or "FailCode"=27 or "FailCode"=35 or "FailCode"=40) as "Ch1",
count (*) FILTER (WHERE "FailCode" =11 or "FailCode"=15 or "FailCode"=19 or "FailCode"=24 or "FailCode"=28 or "FailCode"=36 or "FailCode"=41) as "Ch2",
count (*) FILTER (WHERE "FailCode" =12 or "FailCode"=16 or "FailCode"=20 or "FailCode"=25 or "FailCode"=29 or "FailCode"=37 or "FailCode"=42) as "Ch3",
count (*) FILTER (WHERE "FailCode" =13 or "FailCode"=17 or "FailCode"=21 or "FailCode"=26 or "FailCode"=30 or "FailCode"=38 or "FailCode"=43) as "Ch4"
FROM minical01
where ("FailCode" between 10 and 43) and not ("FailCode" between 31 and 34)
group by 1
) t
where t is not null
group by 5
order by 5
This is what I am getting:
Ch1
Ch2
Ch3
Ch4
Station
61
487
117
57
1
6
13
5
7
2
0
29
17
21
3
283
807
113
510
5
2
0
0
0
6
This is what I am trying to get:
Ch1
Ch2
Ch3
Ch4
Station
61
487
117
57
1
6
13
5
7
2
0
29
17
21
3
0
0
0
0
4
283
807
113
510
5
2
0
0
0
6
0
0
0
0
7
The following is what I tried so far, but it's not changing my results. I still don't get any change:
select
sum("Ch1") AS "Ch1",
sum("Ch2") AS "Ch2",
sum("Ch3") AS "Ch3",
sum("Ch4") AS "Ch4",
CASE WHEN "FailCode" >= 10 and "FailCode" <= 13 THEN 1
WHEN "FailCode" >= 14 and "FailCode" <= 17 THEN 2
WHEN "FailCode" >= 18 and "FailCode" <= 21 THEN 3
WHEN "FailCode" >= 23 and "FailCode" <= 26 THEN 4
WHEN "FailCode" >= 27 and "FailCode" <= 30 THEN 5
WHEN "FailCode" >= 35 and "FailCode" <= 38 THEN 6
WHEN "FailCode" >= 40 and "FailCode" <= 43 THEN 7
END AS station
from (
SELECT "FailCode",
count (*) FILTER (WHERE "FailCode" =10 or "FailCode"=14 or "FailCode"=18 or "FailCode"=23 or "FailCode"=27 or "FailCode"=35 or "FailCode"=40) as "Ch1",
count (*) FILTER (WHERE "FailCode" =11 or "FailCode"=15 or "FailCode"=19 or "FailCode"=24 or "FailCode"=28 or "FailCode"=36 or "FailCode"=41) as "Ch2",
count (*) FILTER (WHERE "FailCode" =12 or "FailCode"=16 or "FailCode"=20 or "FailCode"=25 or "FailCode"=29 or "FailCode"=37 or "FailCode"=42) as "Ch3",
count (*) FILTER (WHERE "FailCode" =13 or "FailCode"=17 or "FailCode"=21 or "FailCode"=26 or "FailCode"=30 or "FailCode"=38 or "FailCode"=43) as "Ch4"
FROM minical01
where ("FailCode" between 10 and 43) and not ("FailCode" between 31 and 34)
group by 1
) t
LEFT JOIN generate_series(1, 7, 1) AS g(id)
ON g.id = t."FailCode"
where t is not null
group by 5
order by 5

Including all months for the year without duplicates when date ranges can be consecutive or not using T-SQL

I have one or more start and end periods which can be consecutive, overlap, or anything in between. My goal is to have all 12 months displayed regardless of when the period starts; that is, I can see months before the period, during the period and potentially after the period. For sake of this example, I'm checking it against 2019 so I want to see all 12 months filled in for 2019.
I have the following sample data to illustrate the problem:
DECLARE #DATES TABLE (ID int, EffectiveDate date, EffectiveEndDate date)
INSERT INTO #DATES
VALUES
(43, '2018-10-01', '2019-09-30'),
(43, '2019-10-01', '2020-09-30'),
(44, '2019-10-01', '2020-09-30');
I also have a "tally" table which has all 12 months and the start of the month (omitted for brevity but it's a temp table with a column called N which has a value of 1-12 representing the month, and a column StartOfMonth which is the start date of the month. Now what I want is to have each ID (43 and 44 in this case) show all 12 months. This is easy with 43 where there are two records that run from October 2018 to November 2020, as it falls within all 12 months. 44 however only gives me October, November and December since there is only one row that begins in October. I cannot add a row for the previous months.
The Months table is simply defined as the follows:
DROP TABLE IF EXISTS #Months;
CREATE TABLE #Months (N tinyint, StartOfMonth date);
INSERT INTO #Months
VALUES
(1, DATEFROMPARTS(2019, 1, 1)),
(2, DATEFROMPARTS(2019, 2, 1)),
(3, DATEFROMPARTS(2019, 3, 1)),
(4, DATEFROMPARTS(2019, 4, 1)),
(5, DATEFROMPARTS(2019, 5, 1)),
(6, DATEFROMPARTS(2019, 6, 1)),
(7, DATEFROMPARTS(2019, 7, 1)),
(8, DATEFROMPARTS(2019, 8, 1)),
(9, DATEFROMPARTS(2019, 9, 1)),
(10, DATEFROMPARTS(2019, 10, 1)),
(11, DATEFROMPARTS(2019, 11, 1)),
(12, DATEFROMPARTS(2019, 12, 1));
Code:
SELECT Month = m.N,
d.ID,
d.EffectiveDate,
d.EffectiveEndDate,
-- This flag doesn't mean anything, just so I can better see the results I'm getting
Ind = CASE
WHEN m.StartOfMonth BETWEEN d.EffectiveDate AND d.EffectiveEndDate
THEN 1
ELSE 0
END
FROM #dates d
LEFT JOIN #Months m
ON m.N BETWEEN 1 AND 12
WHERE
m.StartOfMonth
BETWEEN EffectiveDate AND EffectiveEndDate
ORDER BY ID, m.N;
This gives me the following (wrong) output:
Month ID EffectiveDate EffectiveEndDate Ind
1 43 2018-10-01 2019-09-30 1
2 43 2018-10-01 2019-09-30 1
3 43 2018-10-01 2019-09-30 1
4 43 2018-10-01 2019-09-30 1
5 43 2018-10-01 2019-09-30 1
6 43 2018-10-01 2019-09-30 1
7 43 2018-10-01 2019-09-30 1
8 43 2018-10-01 2019-09-30 1
9 43 2018-10-01 2019-09-30 1
10 43 2019-10-01 2020-09-30 1
11 43 2019-10-01 2020-09-30 1
12 43 2019-10-01 2020-09-30 1
!!! THIS PART IS WRONG !!!
10 44 2019-10-01 2020-09-30 1
11 44 2019-10-01 2020-09-30 1
12 44 2019-10-01 2020-09-30 1
If I skip the effective date/effective end date check or try to do some sort of case statement where I say if month begins before the effective date then include it anyway 43 doubles up on the months because there are two rows, while 44 works as expected.
What I need is to get this:
Month ID EffectiveDate EffectiveEndDate Ind
1 43 2018-10-01 2019-09-30 1
2 43 2018-10-01 2019-09-30 1
3 43 2018-10-01 2019-09-30 1
4 43 2018-10-01 2019-09-30 1
5 43 2018-10-01 2019-09-30 1
6 43 2018-10-01 2019-09-30 1
7 43 2018-10-01 2019-09-30 1
8 43 2018-10-01 2019-09-30 1
9 43 2018-10-01 2019-09-30 1
10 43 2019-10-01 2020-09-30 1
11 43 2019-10-01 2020-09-30 1
12 43 2019-10-01 2020-09-30 1
1 44 2019-10-01 2020-09-30 0
2 44 2019-10-01 2020-09-30 0
3 44 2019-10-01 2020-09-30 0
4 44 2019-10-01 2020-09-30 0
5 44 2019-10-01 2020-09-30 0
6 44 2019-10-01 2020-09-30 0
7 44 2019-10-01 2020-09-30 0
8 44 2019-10-01 2020-09-30 0
9 44 2019-10-01 2020-09-30 0
10 44 2019-10-01 2020-09-30 1
11 44 2019-10-01 2020-09-30 1
12 44 2019-10-01 2020-09-30 1
where all 12 months are showing for all situations, whether there's consecutive ranges or one range that starts at any given point in the year.
There's probably a better way to do this, but here is an ugly solution:
-- Build base data
DECLARE #DATES TABLE (ID int, EffectiveDate date, EffectiveEndDate date)
INSERT INTO #dates
VALUES
(43, '2018-10-01', '2019-09-30'),
(43, '2019-10-01', '2020-09-30'),
(44, '2019-10-01', '2020-09-30');
DECLARE #months TABLE (StartOfMonth date, n int)
;WITH dateCTE
AS
(
SELECT ROW_NUMBER() OVER (ORDER BY number) - 1 AS rn
FROM master.dbo.spt_values
)
INSERT #months (StartOfMonth, n)
SELECT CAST(DATEADD(mm, rn, '2018-01-01') AS date) AS StartOfMonth, DATEPART(mm,DATEADD(mm, rn, '2018-01-01')) AS n
FROM dateCTE
WHERE rn < 48
-- build a list of all IDs and months where the ID is active in the year
;with dateCTE
AS
(
SELECT DISTINCT d.ID, m.StartOfMonth, m.n
FROM #months AS m
CROSS
JOIN #dates AS d
WHERE DATEPART(YEAR,m.StartOfMonth) BETWEEN DATEPART(YEAR,d.EffectiveDate) and DATEPART(YEAR,d.EffectiveEndDate)
)
-- join list from previous step to the activity data
-- this generates the full list with NULLs where the ID was not active
,listCTE
AS
(
SELECT cd.ID, cd.StartOfMonth, cd.n, d.EffectiveDate, d.EffectiveEndDate
FROM dateCTE AS cd
LEFT
JOIN #dates AS d
ON d.ID = cd.ID
AND cd.StartOfMonth between d.EffectiveDate AND d.EffectiveEndDate
)
-- fill in the NULLS by joining the table back to itelf
SELECT n AS [Month],
ID,
COALESCE(EffectiveDate,
(SELECT TOP 1 EffectiveDate FROM listCTE AS l2 WHERE l2.ID = l.ID AND l2.EffectiveDate > l.StartOfMonth ORDER BY l2.StartOfMonth DESC),
(SELECT TOP 1 EffectiveDate FROM listCTE AS l2 WHERE l2.ID = l.ID AND l2.EffectiveEndDate < l.StartOfMonth ORDER BY l2.StartOfMonth DESC)
) AS EffectiveDate,
COALESCE(EffectiveEndDate,
(SELECT TOP 1 EffectiveEndDate FROM listCTE AS l2 WHERE l2.ID = l.ID AND l2.EffectiveDate > l.StartOfMonth ORDER BY l2.StartOfMonth DESC),
(SELECT TOP 1 EffectiveEndDate FROM listCTE AS l2 WHERE l2.ID = l.ID AND l2.EffectiveEndDate < l.StartOfMonth ORDER BY l2.StartOfMonth DESC)
) AS EffectiveEndDate,
CASE
WHEN StartOfMonth BETWEEN EffectiveDate AND EffectiveEndDate
THEN 1
ELSE 0
END AS Ind,
StartOfMonth
FROM listCTE AS l
WHERE DATEPART(YEAR,StartOfMonth) = 2019
ORDER BY ID, StartOfMonth
(This code uses a #months table variable rather than the #months temp table in the original)
This works by building a list of all IDs and months, then left-joining that to the #dates table to generate the months where each ID is active. Finally, the second result set is joined back to itself to fill in the NULLs.
This is likely to have horrible performance when applied to data at scale; it might be possible to mitigate this by materialising the interim steps of the CTEs into tables (or temp tables) with appropriate indexes.

SQL DimDate with Fiscal Year not =454 or 445 but with Calendar Range

I have a script that is working fine with the exception of the fiscal time start/end. For example, year0601 should be the 1st day of the fiscal year and year0530 should be the last day of the fiscal year every year. However, when the script runs, it has an offset. Has anyone scripted this? I'm thinking I can repurpose the calendar login and add +5 to the month logic but wanted to check here first as I've seen a number of 454 and 445 solutions and perhaps I am applying it incorrectly. Thank You for your assistance.
Here is the link to the original code:
https://www.codeproject.com/Articles/647950/%2FArticles%2F647950%2FCreate-and-Populate-Date-Dimension-for-Data-Wareho
`
/*******************************************************************************************************************************************************/
/* Loop on days in interval*/
WHILE (DATEPART(yy,#CurrentDate) <= #LastYear)
BEGIN
/*SET fiscal Month*/
SELECT #FiscalMonth = CASE
/*Use this section for a 4-5-4 calendar. Every leap year the result will be a 4-5-5*/
--WHEN #FiscalWeekOfYear BETWEEN 1 AND 4 THEN 1 /*4 weeks*/
--WHEN #FiscalWeekOfYear BETWEEN 5 AND 9 THEN 2 /*5 weeks*/
--WHEN #FiscalWeekOfYear BETWEEN 10 AND 13 THEN 3 /*4 weeks*/
--WHEN #FiscalWeekOfYear BETWEEN 14 AND 17 THEN 4 /*4 weeks*/
--WHEN #FiscalWeekOfYear BETWEEN 18 AND 22 THEN 5 /*5 weeks*/
--WHEN #FiscalWeekOfYear BETWEEN 23 AND 26 THEN 6 /*4 weeks*/
--WHEN #FiscalWeekOfYear BETWEEN 27 AND 30 THEN 7 /*4 weeks*/
--WHEN #FiscalWeekOfYear BETWEEN 31 AND 35 THEN 8 /*5 weeks*/
--WHEN #FiscalWeekOfYear BETWEEN 36 AND 39 THEN 9 /*4 weeks*/
--WHEN #FiscalWeekOfYear BETWEEN 40 AND 43 THEN 10 /*4 weeks*/
--WHEN #FiscalWeekOfYear BETWEEN 44 AND (48+#LeapWeek) THEN 11 /*5 weeks*/
--WHEN #FiscalWeekOfYear BETWEEN (49+#LeapWeek) AND (52+#LeapWeek) THEN 12 /*4 weeks (5 weeks on leap year)*/
/*Use this section for a 4-4-5 calendar. Every leap year the result will be a 4-5-5*/
WHEN #FiscalWeekOfYear BETWEEN 1 AND 4 THEN 1 /*4 weeks*/
WHEN #FiscalWeekOfYear BETWEEN 5 AND 8 THEN 2 /*4 weeks*/
WHEN #FiscalWeekOfYear BETWEEN 9 AND 13 THEN 3 /*5 weeks*/
WHEN #FiscalWeekOfYear BETWEEN 14 AND 17 THEN 4 /*4 weeks*/
WHEN #FiscalWeekOfYear BETWEEN 18 AND 21 THEN 5 /*4 weeks*/
WHEN #FiscalWeekOfYear BETWEEN 22 AND 26 THEN 6 /*5 weeks*/
WHEN #FiscalWeekOfYear BETWEEN 27 AND 30 THEN 7 /*4 weeks*/
WHEN #FiscalWeekOfYear BETWEEN 31 AND 34 THEN 8 /*4 weeks*/
WHEN #FiscalWeekOfYear BETWEEN 35 AND 39 THEN 9 /*5 weeks*/
WHEN #FiscalWeekOfYear BETWEEN 40 AND 43 THEN 10 /*4 weeks*/
WHEN #FiscalWeekOfYear BETWEEN 44 AND (47+#leapWeek) THEN 11 /*4 weeks (5 weeks on leap year)*/
WHEN #FiscalWeekOfYear BETWEEN (48+#leapWeek) AND (52+#leapWeek) THEN 12 /*5 weeks*/
END
/*SET Fiscal Quarter*/
SELECT #FiscalQuarter = CASE
WHEN #FiscalMonth BETWEEN 1 AND 3 THEN 1
WHEN #FiscalMonth BETWEEN 4 AND 6 THEN 2
WHEN #FiscalMonth BETWEEN 7 AND 9 THEN 3
WHEN #FiscalMonth BETWEEN 10 AND 12 THEN 4
END
SELECT #FiscalQuarterName = CASE
WHEN #FiscalMonth BETWEEN 1 AND 3 THEN 'First'
WHEN #FiscalMonth BETWEEN 4 AND 6 THEN 'Second'
WHEN #FiscalMonth BETWEEN 7 AND 9 THEN 'Third'
WHEN #FiscalMonth BETWEEN 10 AND 12 THEN 'Fourth'
END
/*Set Fiscal Year Name*/
SELECT #FiscalYearName = 'FY ' + CONVERT(VARCHAR, #FiscalYear)
INSERT INTO #tb (PeriodDate, FiscalDayOfYear, FiscalWeekOfYear, fiscalMonth, FiscalQuarter, FiscalQuarterName, FiscalYear, FiscalYearName) VALUES
(#CurrentDate, #FiscalDayOfYear, #FiscalWeekOfYear, #FiscalMonth, #FiscalQuarter, #FiscalQuarterName, #FiscalYear, #FiscalYearName)
/*SET next day*/
SET #CurrentDate = DATEADD(dd, 1, #CurrentDate)
SET #FiscalDayOfYear = #FiscalDayOfYear + 1
SET #FiscalWeekOfYear = ((#FiscalDayOfYear-1) / 7) + 1
IF (#FiscalWeekOfYear > (52+#LeapWeek))
BEGIN
/*Reset a new year*/
SET #FiscalDayOfYear = 1
SET #FiscalWeekOfYear = 1
SET #FiscalYear = #FiscalYear + 1
IF ( EXISTS (SELECT * FROM #leapTable WHERE #FiscalYear = leapyear))
BEGIN
SET #LeapWeek = 1
END
ELSE
BEGIN
SET #LeapWeek = 0
END
END
END
/*******************************************************************************************************************************************************/
/*Set first and last days of the fiscal months*/
UPDATE #tb
SET
FiscalFirstDayOfMonth = minmax.StartDate,
FiscalLastDayOfMonth = minmax.EndDate
FROM
#tb t,
(
SELECT FiscalMonth, FiscalQuarter, FiscalYear, MIN(PeriodDate) AS StartDate, MAX(PeriodDate) AS EndDate
FROM #tb
GROUP BY FiscalMonth, FiscalQuarter, FiscalYear
) minmax
WHERE
t.FiscalMonth = minmax.FiscalMonth AND
t.FiscalQuarter = minmax.FiscalQuarter AND
t.FiscalYear = minmax.FiscalYear
/*Set first and last days of the fiscal quarters*/
UPDATE #tb
SET
FiscalFirstDayOfQuarter = minmax.StartDate,
FiscalLastDayOfQuarter = minmax.EndDate
FROM
#tb t,
(
SELECT FiscalQuarter, FiscalYear, min(PeriodDate) as StartDate, max(PeriodDate) as EndDate
FROM #tb
GROUP BY FiscalQuarter, FiscalYear
) minmax
WHERE
t.FiscalQuarter = minmax.FiscalQuarter AND
t.FiscalYear = minmax.FiscalYear
/*Set first and last days of the fiscal years*/
UPDATE #tb
SET
FiscalFirstDayOfYear = minmax.StartDate,
FiscalLastDayOfYear = minmax.EndDate
FROM
#tb t,
(
SELECT FiscalYear, min(PeriodDate) as StartDate, max(PeriodDate) as EndDate
FROM #tb
GROUP BY FiscalYear
) minmax
WHERE
t.FiscalYear = minmax.FiscalYear
/*Set FiscalYearMonth*/
UPDATE #tb
SET
FiscalMonthYear =
CASE FiscalMonth
WHEN 1 THEN 'Jun'
WHEN 2 THEN 'Jul'
WHEN 3 THEN 'Aug'
WHEN 4 THEN 'Sep'
WHEN 5 THEN 'Oct'
WHEN 6 THEN 'Nov'
WHEN 7 THEN 'Dec'
WHEN 8 THEN 'Jan'
WHEN 9 THEN 'Feb'
WHEN 10 THEN 'Mar'
WHEN 11 THEN 'Apr'
WHEN 12 THEN 'May'
END + '-' + CONVERT(VARCHAR, FiscalYear)
/*Set FiscalMMYYYY*/
UPDATE #tb
SET
FiscalMMYYYY = RIGHT('0' + CONVERT(VARCHAR, FiscalMonth),2) + CONVERT(VARCHAR, FiscalYear)
/*******************************************************************************************************************************************************/

Sum up items between setup of custom times

We need to count the number of items that occur 10 minutes before and 10 minutes after the hour, by day. We have a table that tracks the items individually. Ideally i would like to have the output be something like the below, but and totally open to other suggestions.
Table - Attendance
Att_item timestamp
1 2012-09-12 18:08:00
2 2012-09-01 23:26:00
3 2012-09-23 09:33:00
4 2012-09-11 09:43:00
5 2012-09-06 05:57:00
6 2012-09-17 19:26:00
7 2012-09-06 10:51:00
8 2012-09-19 09:42:00
9 2012-09-06 13:55:00
10 2012-09-05 07:26:00
11 2012-09-02 03:08:00
12 2012-09-19 12:17:00
13 2012-09-12 18:14:00
14 2012-09-12 18:14:00
Output
Date Timeslot_5pm Timeslot_6pm Timeslot_7pm
9/11/2012 11 22 22
9/12/2012 30 21 55
9/13/2012 44 33 44
Your requirements are not totally clear, but if you only want to count the number of records in the 20 minute window:
select cast(tstmp as date) date,
sum(case when datepart(hour, tstmp) = 1 then 1 else 0 end) Timeslot_1am,
sum(case when datepart(hour, tstmp) = 2 then 1 else 0 end) Timeslot_2am,
sum(case when datepart(hour, tstmp) = 3 then 1 else 0 end) Timeslot_3am,
sum(case when datepart(hour, tstmp) = 4 then 1 else 0 end) Timeslot_4am,
sum(case when datepart(hour, tstmp) = 5 then 1 else 0 end) Timeslot_5am,
sum(case when datepart(hour, tstmp) = 6 then 1 else 0 end) Timeslot_6am,
sum(case when datepart(hour, tstmp) = 7 then 1 else 0 end) Timeslot_7am,
sum(case when datepart(hour, tstmp) = 8 then 1 else 0 end) Timeslot_8am,
sum(case when datepart(hour, tstmp) = 9 then 1 else 0 end) Timeslot_9am,
sum(case when datepart(hour, tstmp) = 10 then 1 else 0 end) Timeslot_10am,
sum(case when datepart(hour, tstmp) = 11 then 1 else 0 end) Timeslot_11am,
sum(case when datepart(hour, tstmp) = 12 then 1 else 0 end) Timeslot_12pm,
sum(case when datepart(hour, tstmp) = 13 then 1 else 0 end) Timeslot_1pm,
sum(case when datepart(hour, tstmp) = 14 then 1 else 0 end) Timeslot_2pm,
sum(case when datepart(hour, tstmp) = 15 then 1 else 0 end) Timeslot_3pm,
sum(case when datepart(hour, tstmp) = 16 then 1 else 0 end) Timeslot_4pm,
sum(case when datepart(hour, tstmp) = 17 then 1 else 0 end) Timeslot_5pm,
sum(case when datepart(hour, tstmp) = 18 then 1 else 0 end) Timeslot_6pm,
sum(case when datepart(hour, tstmp) = 19 then 1 else 0 end) Timeslot_7pm,
sum(case when datepart(hour, tstmp) = 20 then 1 else 0 end) Timeslot_8pm,
sum(case when datepart(hour, tstmp) = 21 then 1 else 0 end) Timeslot_9pm,
sum(case when datepart(hour, tstmp) = 22 then 1 else 0 end) Timeslot_10pm,
sum(case when datepart(hour, tstmp) = 23 then 1 else 0 end) Timeslot_11pm
from yourtable
where datepart(minute, tstmp) >= 50
or datepart(minute, tstmp) <= 10
group by cast(tstmp as date)
If you want to count the number of records within each hour plus the records that are in the >=50 and <= 10 timeframe, then you will have to adjust this.
This does just one column (well 4 but you get my point).
select DATEPART(YYYY, FTSdate) as [year], DATEPART(mm, FTSdate) as [month]
, DATEPART(dd, FTSdate) as [day], DATEPART(hh, FTSdate) as [hour], COUNT(*)
from [Gabe2a].[dbo].[docSVsys]
where DATEPART(mi, FTSdate) >= 50 or DATEPART(mi, FTSdate) <= 10
group by DATEPART(YYYY, FTSdate), DATEPART(mm, FTSdate), DATEPART(dd, FTSdate), DATEPART(hh, FTSdate)
order by DATEPART(YYYY, FTSdate), DATEPART(mm, FTSdate), DATEPART(dd, FTSdate), DATEPART(hh, FTSdate)
Separate columns.
select DATEPART(YYYY, FTSdate) as [year], DATEPART(mm, FTSdate) as [month]
, DATEPART(dd, FTSdate) as [day]
, sum(case when DATEPART(hh, FTSdate) = '0' then 1 else 0 end) as [0:00] -- midnight
, sum(case when DATEPART(hh, FTSdate) = '1' then 1 else 0 end) as [1:00]
, sum(case when DATEPART(hh, FTSdate) = '2' then 1 else 0 end) as [2:00]
, sum(case when DATEPART(hh, FTSdate) = '3' then 1 else 0 end) as [3:00]
, sum(case when DATEPART(hh, FTSdate) = '4' then 1 else 0 end) as [4:00]
from [Gabe2a].[dbo].[docSVsys]
where DATEPART(mi, FTSdate) >= 50 or DATEPART(mi, FTSdate) <= 10
group by DATEPART(YYYY, FTSdate), DATEPART(mm, FTSdate), DATEPART(dd, FTSdate)
order by DATEPART(YYYY, FTSdate), DATEPART(mm, FTSdate), DATEPART(dd, FTSdate)

How do I add totals/subtotals to a set of results without grouping the row data?

I'm constructing a SQL query for a business report. I need to have both subtotals (grouped by file number) and grand totals on the report.
I'm entering unknown SQL territory, so this is a bit of a first attempt. The query I made is almost working. The only problem is that the entries are being grouped -- I need them separated in the report.
Here is my sample data:
FileNumber Date Cost Charge
3 Dec 22/09 5 10
3 Jan 13/10 6 15
3B Mar 28/10 1 3
3B Mar 28/10 5 10
When I run this query
SELECT
CASE
WHEN (GROUPING(FileNumber) = 1) THEN NULL
ELSE FileNumber
END AS FileNumber,
CASE
WHEN (GROUPING(Date) = 1) THEN NULL
ELSE Date
END AS Date,
SUM(Cost) AS Cost,
SUM(Charge) AS Charge
FROM SubtotalTesting
GROUP BY FileNumber, Date WITH ROLLUP
ORDER BY
(CASE WHEN FileNumber IS NULL THEN 1 ELSE 0 END), -- Put NULLs after data
FileNumber,
(CASE WHEN Date IS NULL THEN 1 ELSE 0 END), -- Put NULLs after data
Date
I get the following:
FileNumber Date Cost Charge
3 Dec 22/09 5 10
3 Jan 13/10 6 15
3 NULL 11 25
3B Mar 28/10 6 13 <--
3B NULL 6 13
NULL NULL 17 38
What I want is:
FileNumber Date Cost Charge
3 Dec 22/09 5 10
3 Jan 13/10 6 15
3 NULL 11 25
3B Mar 28/10 1 3 <--
3B Mar 28/10 5 10 <--
3B NULL 6 13
NULL NULL 17 38
I can clearly see why the entries are being grouped, but I have no idea how to separate them while still returning the subtotals and grand total.
I'm a bit green when it comes to doing advanced SQL queries like this, so if I'm taking the wrong approach to the problem by using WITH ROLLUP, please suggest some preferred alternatives -- you don't have to write the whole query for me, I just need some direction. Thanks!
WITH SubtotalTesting (FileNumber, Date, Cost, Charge) AS
(
SELECT '3', CAST('2009-22-12' AS DATETIME), 5, 10
UNION ALL
SELECT '3', '2010-13-06', 6, 15
UNION ALL
SELECT '3B', '2010-28-03', 1, 3
UNION ALL
SELECT '3B', '2010-28-03', 5, 10
),
q AS (
SELECT *,
ROW_NUMBER() OVER (ORDER BY filenumber) AS rn
FROM SubTotalTesting
)
SELECT rn,
CASE
WHEN (GROUPING(FileNumber) = 1) THEN NULL
ELSE FileNumber
END AS FileNumber,
CASE
WHEN (GROUPING(Date) = 1) THEN NULL
ELSE Date
END AS Date,
SUM(Cost) AS Cost,
SUM(Charge) AS Charge
FROM q
GROUP BY
FileNumber, Date, rn WITH ROLLUP
HAVING GROUPING(rn) <= GROUPING(Date)
ORDER BY
(CASE WHEN FileNumber IS NULL THEN 1 ELSE 0 END),
FileNumber,
(CASE WHEN Date IS NULL THEN 1 ELSE 0 END),
Date