Tsql unique records grouping - tsql

I am using SSMS 2008 R2 and I'm trying to condense output from this query into one line / full_name. How do I do this? Here is my query:
select top 500
CASE when pv.conversion_id_no is not null then pv.conversion_id_no else prv.id_no end as id_number,
eiev.full_name,
eiev.dob,
ep.start_date as yvdoa,
ep.end_date as yvdod,
e4pv.actual_date,
test_header_x.OUTCM_FLWUP_SRVY_PERIOD,
l.description as Call_Location,
case when tqav.question_caption like 'Custody at Follow-up%' then answer_caption end as Custody,
case when tqav.answer_caption like 'Residential Treatment Center%' then answer_is_selected end as RTC,
case when tqav.answer_caption like 'Psychiatric Hospital%' then answer_is_selected end as PsychHosp,
case when tqav.answer_caption like 'Juvenile Detention/Corrections or Adult Jail%' then answer_is_selected end as Corrections,
case when tqav.question_caption like 'Has the youth been attending school?%' then answer_caption end as AttendingSchool,
case when tqav.question_caption like 'Why is the youth not attending school%' then answer_caption end as SchoolStatus,
case when tqav.question_caption like 'Has youth been in trouble with the law/legal system%' then answer_caption end as TroubleLaw
from dbo.rpt_events_4people_view as e4pv
JOIN dbo.rpt_test_questions_answers_view as tqav on e4pv.event_log_id = tqav.event_log_id
left JOIN dbo.enrollment_info_expanded_view as eiev on eiev.people_id = e4pv.people_id
JOIN dbo.rpt_episod_of_care_program_view as ep on eiev.people_id = ep.people_id and ep.program_info_id = eiev.program_info
JOIN dbo.people_reports_view as prv on e4pv.people_id = prv.people_id
JOIN evolv_cs.dbo.test_details_answers_expanded_view as tdaev on tdaev.event_log_id = e4pv.event_log_id
JOIN evolv_cs.dbo.user_defined_lut as l ON tdaev.picklist_value = l.user_defined_lut_id
left outer JOIN dbo.people_rv as pv on eiev.people_id = pv.people_id
left JOIN [evolv_reports].[dbo].[test_header_rv] With (NoLock) ON e4pv.[event_log_id] = [test_header_rv].[event_log_id]
left JOIN evolv_cs.dbo.Test_header_x With (NoLock) ON test_header_x.test_header_id = test_header_rv.test_header_id
where e4pv.event_name = 'Outcome Follow-up Survey'
and e4pv.actual_date between '10/01/2011' and '03/31/2012'
and ep.program_name in ('In-Home Services - Intercept')
and (tqav.question_caption like 'Custody at Follow-up%' or
tqav.answer_caption like 'Residential Treatment Center%' or
tqav.answer_caption like 'Psychiatric Hospital%' or
tqav.answer_caption like 'Juvenile Detention/Corrections or Adult Jail%' or
tqav.question_caption like 'Has the youth been attending school?%' or
tqav.question_caption like 'Why is the youth not attending school%' or
tqav.question_caption like 'Has youth been in trouble with the law/legal system%' )
and ((eiev.profile_name like '%Lic.# NH%' and ep.start_date >= '02/01/2011')
or (eiev.profile_name like '%Lic.# MA%' and ep.start_date >= '02/01/2011')
or (eiev.profile_name like '%Lic.# DC%' and ep.start_date >= '05/01/2011')
or (eiev.profile_name like '%Lic.# NC%' and ep.start_date >= '05/01/2011')
or (eiev.profile_name like '%Lic.# FL%' and ep.start_date >= '07/18/2011')
or (eiev.profile_name like '%Lic.# TX%' and ep.start_date >= '07/18/2011')
or (eiev.profile_name like '%Lic.# AL%' and ep.start_date >= '02/01/2012')
or (eiev.profile_name like '%Lic.# GA%' and ep.start_date >= '02/01/2012')
or (eiev.profile_name like '%Lic.# OR%' and ep.start_date >= '03/01/2012'))
and DATEDIFF (dd,ep.start_date, ep.end_date) >= 60
Right now my output from this looks like:
id_number full_name dob yvdoa yvdod actual_date OUTCM_FLWUP_SRVY_PERIOD Call_Location Custody RTC PsychHosp Corrections AttendingSchool SchoolStatus TroubleLaw
10169613 Anderson, Mason 1996-02-06 00:00:00.000 2011-02-07 12:00:00.000 2011-09-04 23:59:00.000 2012-03-30 00:00:00.000 28094354-A0B4-428C-B38A-B90835DAF896 No Response Not available NULL NULL NULL NULL NULL NULL
10169613 Anderson, Mason 1996-02-06 00:00:00.000 2011-02-07 12:00:00.000 2011-09-04 23:59:00.000 2012-03-30 00:00:00.000 28094354-A0B4-428C-B38A-B90835DAF896 No Response NULL NULL NULL NULL NULL NULL NULL
10169613 Anderson, Mason 1996-02-06 00:00:00.000 2011-02-07 12:00:00.000 2011-09-04 23:59:00.000 2012-03-30 00:00:00.000 28094354-A0B4-428C-B38A-B90835DAF896 No Response NULL NULL NULL NULL NULL NULL NULL
10169613 Anderson, Mason 1996-02-06 00:00:00.000 2011-02-07 12:00:00.000 2011-09-04 23:59:00.000 2012-03-30 00:00:00.000 28094354-A0B4-428C-B38A-B90835DAF896 No Response NULL NULL NULL 0 NULL NULL NULL
10169613 Anderson, Mason 1996-02-06 00:00:00.000 2011-02-07 12:00:00.000 2011-09-04 23:59:00.000 2012-03-30 00:00:00.000 28094354-A0B4-428C-B38A-B90835DAF896 No Response NULL NULL 0 NULL NULL NULL NULL
10169613 Anderson, Mason 1996-02-06 00:00:00.000 2011-02-07 12:00:00.000 2011-09-04 23:59:00.000 2012-03-30 00:00:00.000 28094354-A0B4-428C-B38A-B90835DAF896 No Response NULL 0 NULL NULL NULL NULL NULL
So you will see that the answer fields can be VARCHAR values, which is why I can't simply SUM all of the answers.

Little-known fact: you can actually use MAX() to pick out the non-null varchar from your result set.
Suppose you have the following schema:
TABLE A:
a_id name
1 fruit
2 names
TABLE Vals:
a_id value_type value
1 a apple
1 b banana
1 c carrot
2 a alice
2 b bob
2 c carol
Then you can use MAX and GROUP BY to get one row per item in A listing each value type.
SELECT A.a_id,
A.name,
MAX(CASE WHEN V.value_type = 'a' then value end) as "a",
MAX(CASE WHEN V.value_type = 'b' then value end) as "b",
MAX(CASE WHEN V.value_type = 'c' then value end) as "c"
FROM A
INNER JOIN Vals V on V.a_id = A.a_id
GROUP BY A.a_id, A.name
See it on sqlfiddle here: http://sqlfiddle.com/#!3/aba0a/1

Related

Repeating value of previous row in a join

I have one table including accounts and their balance. I would like to report the balance for each day while for missing days report the last day.
Table accounts:
AccountName Date Balance
thomas 2008-10-09 1000
thomas 2008-10-20 5000
david 2008-02-18 2000
david 2008-03-10 200000
let's say we want the report for 2018-10 I need to get something like this
thomas 2008-10-01 0
...
thomas 2008-10-09 1000
thomas 2008-10-10 1000
...
thomas 2008-10-20 5000
...
thomas 2008-10-31 5000
I went this far:
DECLARE #StartDate datetime = '2008/10/9';
DECLARE #EndDate datetime = '2008/10/20';
WITH theDates AS
(
SELECT #StartDate as theDate
UNION ALL
SELECT DATEADD(day, 1, theDate)
FROM theDates
WHERE DATEADD(day, 1, theDate) <= #EndDate
)
select * from accounts a
right outer join thedates d on a.date=d.theDate
order by thedate
Results:
AccountNo Date Balance theDate
----------- ---------- -------- ----------
thomas 2008-10-09 1000 2008-10-09
NULL NULL NULL 2008-10-10
NULL NULL NULL 2008-10-11
NULL NULL NULL 2008-10-12
NULL NULL NULL 2008-10-13
NULL NULL NULL 2008-10-14
NULL NULL NULL 2008-10-15
NULL NULL NULL 2008-10-16
NULL NULL NULL 2008-10-17
NULL NULL NULL 2008-10-18
NULL NULL NULL 2008-10-19
thomas 2008-10-20 5000 2008-10-20
Any idea?
Update:
I end up using cursor. This is version working perfectly including the situation where an account has no entry.
DECLARE #Date datetime
declare #result table (accountname nvarchar(50), balance int, date datetime)
DECLARE #StartDate datetime = '2008/10/1';
DECLARE #EndDate datetime = '2008/10/29';
declare cur cursor for
WITH theDates AS
(
SELECT #StartDate as theDate
UNION ALL
SELECT DATEADD(day, 1, theDate)
FROM theDates
WHERE DATEADD(day, 1, theDate) <= #EndDate
)
select * from theDates
open cur
fetch next from cur into #date
while ##FETCH_STATUS=0
begin
insert into #result
select b.accountName, isnull(balance,
(select isnull((select top 1 balance from accounts where date<#date and accountName=b.accountName order by date desc),0))
), #date from
(select * from accounts where date = #date) a
right outer join (select distinct(accountname) from accounts ) b on a.accountname = b.accountname
fetch next from cur into #date
end
close cur
deallocate cur
select * from #result
Try this:
DECLARE #StartDate datetime = '2008/10/9';
DECLARE #EndDate datetime = '2008/10/20';
WITH theDates AS
(
SELECT #StartDate as theDate
UNION ALL
SELECT DATEADD(day, 1, theDate)
FROM theDates
WHERE DATEADD(day, 1, theDate) <= #EndDate
),
acc AS(
SELECT a.AccountName,
a.Balance,
a.Date,
isnull(c.CloseDate, cast(GETDATE()as date)) as CloseDate
FROM accounts a
CROSS APPLY(SELECT MIN(b.Date) as CloseDate
FROM accounts b
WHERE b.Date > a.Date) c
)
SELECT a.AccountName, a.Balance, a.Date, d.theDate
FROM acc a, theDates d
WHERE a.Date <= d.theDate
AND a.CloseDate > d.theDate
option (maxrecursion 0)
Results:
AccountName Balance Date theDate
----------- ----------- ------------------- -----------------------
thomas 1000 2008-10-09 00:00:00 2008-10-09 00:00:00.000
thomas 1000 2008-10-09 00:00:00 2008-10-10 00:00:00.000
thomas 1000 2008-10-09 00:00:00 2008-10-11 00:00:00.000
thomas 1000 2008-10-09 00:00:00 2008-10-12 00:00:00.000
thomas 1000 2008-10-09 00:00:00 2008-10-13 00:00:00.000
thomas 1000 2008-10-09 00:00:00 2008-10-14 00:00:00.000
thomas 1000 2008-10-09 00:00:00 2008-10-15 00:00:00.000
thomas 1000 2008-10-09 00:00:00 2008-10-16 00:00:00.000
thomas 1000 2008-10-09 00:00:00 2008-10-17 00:00:00.000
thomas 1000 2008-10-09 00:00:00 2008-10-18 00:00:00.000
thomas 1000 2008-10-09 00:00:00 2008-10-19 00:00:00.000
thomas 5000 2008-10-20 00:00:00 2008-10-20 00:00:00.000
You can try to use aggregate function MIN and MAX make calendar table then OUTER JOIN
WITH theDates AS
(
SELECT AccountName, MIN(Date) as StartDt,MAX(Date) EndDt
FROM accounts
GROUP BY AccountName
UNION ALL
SELECT AccountName,DATEADD(day, 1, StartDt),EndDt
FROM theDates
WHERE DATEADD(day, 1, StartDt) <= EndDt
)
select d.AccountName,
d.StartDt [date],
ISNULL(a.Balance,0) Balance
from accounts a
LEFT join thedates d on a.date=d.StartDt
order by StartDt

PIVOT not producing data on a single row

I am trying to write PIVOT to generate a row of data that originally sits as multiple rows in the DB. The DB data looks like this (appended)
txtSchoolID txtSubjectArchivedName intSubjectID intGradeID intGradeTransposeValue
95406288448 History 7 634 2
95406288448 History 7 635 2
95406288448 History 7 636 2
95406288448 History 7 637 2
95406288448 History 7 638 2
95406288448 History 7 639 2
95406288448 History 7 640 2
95406288448 History 7 641 2
95406288448 History 7 642 2
95406288448 History 7 643 2
What I want to get to is 1 row for each subject and SchoolID with the grades listed as columns.
I have written the following pivot:
SELECT intSubjectID, txtSchoolID, [636] AS Effort, [637] AS Focus, [638] AS Participation, [639] AS Groupwork, [640] AS Rigour, [641] AS Curiosity, [642] AS Initiative,
[643] AS SelfOrganisation, [644] as Perserverance
FROM (SELECT txtSchoolID, intReportTypeID, txtSubjectArchivedName, intSubjectID, intReportProgress, txtTitle, txtForename, txtPreName, txtMiddleNames,
txtSurname, txtGender, txtForm, intNCYear, txtSubmitByTitle, txtSubmitByPreName, txtSubmitByFirstname, txtSubmitByMiddleNames,
txtSubmitBySurname, txtCurrentSubjectName, txtCurrentSubjectReportName, intReportCycleID, txtReportCycleName, intReportCycleType,
intPreviousReportCycle, txtReportCycleShortName, intReportCycleTerm, intReportCycleAcademicYear, dtReportCycleStartDate,
dtReportCycleFinishDate, dtReportCyclePrintDate, txtReportTermName, dtReportTermStartDate, dtReportTermFinishDate,
intGradeID, txtGradingName, txtGradingOptions, txtShortGradingName, txtGrade, intGradeTransposeValue FROM VwReportsManagementAcademicReports) p
PIVOT
(MAX (intGradeTransposeValue)
FOR intGradeID IN ([636], [637], [638], [639], [640], [641], [642], [643], [644] )
) AS pvt
WHERE (intReportCycleID = 142) AND (intReportProgress = 1)
However, this is producing this
intSubjectID txtSchoolID Effort Focus Participation Groupwork Rigour Curiosity Initiative SelfOrganisation Perserverance
8 74001484142 NULL NULL NULL NULL NULL NULL NULL NULL NULL
8 74001484142 NULL NULL NULL NULL NULL 2 NULL NULL NULL
8 74001484142 3 NULL NULL NULL NULL NULL NULL NULL NULL
8 74001484142 NULL 2 NULL NULL NULL NULL NULL NULL NULL
8 74001484142 NULL NULL NULL 2 NULL NULL NULL NULL NULL
8 74001484142 NULL NULL NULL NULL NULL NULL 2 NULL NULL
8 74001484142 NULL NULL 2 NULL NULL NULL NULL NULL NULL
8 74001484142 NULL NULL NULL NULL NULL NULL NULL NULL 2
8 74001484142 NULL NULL NULL NULL 2 NULL NULL NULL NULL
8 74001484142 NULL NULL NULL NULL NULL NULL NULL 2 NULL
What I want is
intSubjectID txtSchoolID Effort Focus Participation Groupwork Rigour Curiosity Initiative SelfOrganisation Perserverance
8 74001484142 3 2 2 2 2 2 2 2 2
Is there a way to get it like this.
I have never tried a PIVOT before, this is my first time, so all help welcome.
I think the reason you got the unexpected result is you have so many unwanted columns in the Select in the sub-query and the pivot will group them, too.
Your query might be very close to your ideal result: try:
SELECT intSubjectID, txtSchoolID, [636] AS Effort, [637] AS Focus, [638] AS Participation, [639] AS Groupwork, [640] AS Rigour, [641] AS Curiosity, [642] AS Initiative,
[643] AS SelfOrganisation, [644] as Perserverance
FROM (SELECT txtSchoolID, intReportTypeID FROM VwReportsManagementAcademicReports) p --just these two
PIVOT
(MAX (intGradeTransposeValue)
FOR intGradeID IN ([636], [637], [638], [639], [640], [641], [642], [643], [644] )
) AS pvt
WHERE (intReportCycleID = 142) AND (intReportProgress = 1)
As per the comment above - the solution was:
try stripping the inner select down to only the columns that will be used in the pivot and are expected in the output. intSubjectID, txtSchoolID, intGradeTransposeValue, and intGradeID. all other columns will act as a grouping column in the output and can cause this type of non grouped output.
pivot can't return such what you asking for, but you can use another approach:
--test dataset
declare #test as table
( txtSchoolID bigint,
txtSubjectArchivedName varchar(10),
intSubjectID int,
intGradeID int,
intGradeTransposeValue int)
insert into #test
Values
(95406288448,'History',7,634,2),
(95406288448,'History',7,635,2),
(95406288448,'History',7,636,2),
(95406288448,'History',7,637,2),
(95406288448,'History',7,638,2),
(95406288448,'History',7,639,2),
(95406288448,'History',7,640,2),
(95406288448,'History',7,641,2),
(95406288448,'History',7,642,2),
(95406288448,'History',7,643,2)
--conditional aggregation
select intSubjectID,
txtSchoolID,
count(case when intGradeID = 636 then 1 end) AS Effort,
count(case when intGradeID = 637 then 1 end) AS Focus,
count(case when intGradeID = 638 then 1 end) AS Participation,
count(case when intGradeID = 639 then 1 end) AS Groupwork,
count(case when intGradeID = 640 then 1 end) AS Rigour,
count(case when intGradeID = 641 then 1 end) AS Curiosity,
count(case when intGradeID = 642 then 1 end) AS Initiative,
count(case when intGradeID = 643 then 1 end) AS SelfOrganisation,
count(case when intGradeID = 644 then 1 end) as Perserverance
from #test
group by intSubjectID, txtSchoolID
test is here

Using an AND statement in a CASE in t sql

I am trying to make a case statement where one of the WHEN's contains an AND.
Declare #FROM DateTime = 'OCT 1 2015 12:00AM'
,case when isnull(SS.VerificationFlag,0) = 1 then 1
when isnull(SS.ExperationDate1,#FROM) >= #FROM AND isnull(SS.ExperationDate2,#FROM) >= #FROM then 1
else 0
END
I am getting a 1 as output when ExperationDate1 passes and ExperationDate2 fails.
Thank you.
There is nothing wrong with your case statement. I tried it in a select clause and it works as expected. I believe that you're getting a 1 because the first case is true. That is:
when isnull(SS.VerificationFlag,0) = 1 then 1
fires before you get to the more complicated clause with an AND statement.
DROP TABLE SS;
go
create table SS (
VerificationFlag tinyint,
ExpirationDate1 datetime,
ExpirationDate2 datetime
)
INSERT INTO SS(VerificationFlag, ExpirationDate1, ExpirationDate2) VALUES (0, NULL, NULL)
INSERT INTO SS(VerificationFlag, ExpirationDate1, ExpirationDate2) VALUES (0, '20140214', NULL)
INSERT INTO SS(VerificationFlag, ExpirationDate1, ExpirationDate2) VALUES (0, NULL, '20160619')
INSERT INTO SS(VerificationFlag, ExpirationDate1, ExpirationDate2) VALUES (0, '20140214', '20160619')
INSERT INTO SS(VerificationFlag, ExpirationDate1, ExpirationDate2) VALUES (1, NULL, NULL)
INSERT INTO SS(VerificationFlag, ExpirationDate1, ExpirationDate2) VALUES (1, '20140214', NULL)
INSERT INTO SS(VerificationFlag, ExpirationDate1, ExpirationDate2) VALUES (1, NULL, '20160619')
INSERT INTO SS(VerificationFlag, ExpirationDate1, ExpirationDate2) VALUES (1, '20140214', '20160619')
INSERT INTO SS(VerificationFlag, ExpirationDate1, ExpirationDate2) VALUES (1, NULL, NULL)
INSERT INTO SS(VerificationFlag, ExpirationDate1, ExpirationDate2) VALUES (1, '20160214', NULL)
INSERT INTO SS(VerificationFlag, ExpirationDate1, ExpirationDate2) VALUES (1, NULL, '20140619')
INSERT INTO SS(VerificationFlag, ExpirationDate1, ExpirationDate2) VALUES (1, '20160214', '20140619')
INSERT INTO SS(VerificationFlag, ExpirationDate1, ExpirationDate2) VALUES (0, '20160214', '20140619')
DECLARE #from DATETIME;
SET #from = '20151001';
SELECT
SS.VerificationFlag,
SS.ExpirationDate1,
SS.ExpirationDate2,
#from AS FromDate,
CASE
WHEN ISNULL(SS.VerificationFlag, 0) = 1 THEN 1
WHEN (ISNULL(SS.ExpirationDate1, #from) >= #from) AND (ISNULL(SS.ExpirationDate2, #from) >= #from) THEN 1
ELSE 0
END AS ResultingFlag
FROM SS
With results:
VerificationFlag ExpirationDate1 ExpirationDate2 FromDate ResultingFlag
---------------- ----------------------- ----------------------- ----------------------- -------------
0 NULL NULL 2015-10-01 00:00:00.000 1
0 2014-02-14 00:00:00.000 NULL 2015-10-01 00:00:00.000 0
0 NULL 2016-06-19 00:00:00.000 2015-10-01 00:00:00.000 1
0 2014-02-14 00:00:00.000 2016-06-19 00:00:00.000 2015-10-01 00:00:00.000 0
1 NULL NULL 2015-10-01 00:00:00.000 1
1 2014-02-14 00:00:00.000 NULL 2015-10-01 00:00:00.000 1
1 NULL 2016-06-19 00:00:00.000 2015-10-01 00:00:00.000 1
1 2014-02-14 00:00:00.000 2016-06-19 00:00:00.000 2015-10-01 00:00:00.000 1
1 NULL NULL 2015-10-01 00:00:00.000 1
1 2016-02-14 00:00:00.000 NULL 2015-10-01 00:00:00.000 1
1 NULL 2014-06-19 00:00:00.000 2015-10-01 00:00:00.000 1
1 2016-02-14 00:00:00.000 2014-06-19 00:00:00.000 2015-10-01 00:00:00.000 1
0 2016-02-14 00:00:00.000 2014-06-19 00:00:00.000 2015-10-01 00:00:00.000 0

Forming a Tsql query that ranks and categorizes date field

I have this datset:
create table #date_example
(
date_val datetime, rownum int
)
insert #date_example values('3/1/14',1)
insert #date_example values('3/1/14',2)
insert #date_example values('3/1/14',3)
insert #date_example values('2/1/14',4)
insert #date_example values('1/3/14',5)
select --top 1 with ties
date_val,
ROW_NUMBER() OVER(PARTITION BY rownum ORDER BY date_val DESC) AS 'RowNum'
from #date_example
order by date_val
desc
With output:
date_val RowNum
2014-03-01 00:00:00.000 1
2014-03-01 00:00:00.000 1
2014-03-01 00:00:00.000 1
2014-02-01 00:00:00.000 1
2014-01-03 00:00:00.000 1
But I want instead output:
date_val RowNum
2014-03-01 00:00:00.000 1
2014-03-01 00:00:00.000 1
2014-03-01 00:00:00.000 1
2014-02-01 00:00:00.000 2
2014-01-03 00:00:00.000 3
So I want the RowNum to be a ranking which includes ties. How can I do this?
I found the answer from another post:
select
date_val,
Rank() OVER(ORDER BY date_val DESC) AS 'RowNum'
from #date_example

Understanding TSQL Coalesce function

I am trying to select all 12 months / year. And I thought following TSQL code would do this. However, this does not include all months like I want. What is the cause of this? This is modified code:
DECLARE #END_YEAR VARCHAR(10)
DECLARE #END_MONTH VARCHAR(10)
SET #END_YEAR = '2010'
SET #END_MONTH = '10'
DECLARE #TheMonthLastDate DATETIME
DECLARE #TempDate DATETIME
SET #TempDate = '2010-11-01 00:00:00.000'
SET #TheMonthLastDate = '2010-11-01 00:00:00.000'
;with months
as
(
select dateadd(month, -1, dateadd(day, datediff(day, 0, #TempDate), 0)) as m
union all
select dateadd(month, -1, m)
from months
where m > dateadd(month, -12, #TempDate)
)
,yourTable(DateOpened, DateClosed)
as
(select TSK_START_DATE, BTK_CLOSED_DATE
FROM [PROC].ALL_AUDIT
WHERE
(BTK_CLOSED_DATE < #TheMonthLastDate OR
TSK_START_DATE < #TheMonthLastDate
)
)
select yt.DateClosed 'r2', m.m 'r3',
month(coalesce(yt.DateClosed, m.m)) as 'MonthClosed',
year(coalesce(yt.DateClosed, m.m)) as 'YearClosed'
from months m
left join yourTable yt
on
( datepart(year, yt.DateClosed) = DATEPART(year, m.m)
and datepart(month, yt.DateClosed) = DATEPART(month, m.m)
or
datepart(year, yt.DateOpened) = DATEPART(year, m.m)
and datepart(month, yt.DateOpened) = DATEPART(month, m.m)
)
AND year(coalesce(yt.DateClosed, m.m)) = 2010
order by yt.DateClosed
So above query does not return all months. But if I change above WHERE lines to:
FROM [PROC].ALL_AUDIT
WHERE
BTK_CLOSED_DATE < #TheMonthLastDate
then this query does return all 12 months. How can this be?
Output that I want and that I see when WHERE is BTK_CLOSED_DATE < #TheMonthLastDate:
r2 r3 MonthClosed YearClosed
NULL 2010-06-01 00:00:00.000 6 2010
NULL 2009-11-01 00:00:00.000 11 2009
2010-01-06 20:02:19.127 2010-01-01 00:00:00.000 1 2010
2010-01-27 23:13:45.570 2010-01-01 00:00:00.000 1 2010
2010-02-15 14:49:14.427 2010-02-01 00:00:00.000 2 2010
2010-02-15 14:49:14.427 2009-12-01 00:00:00.000 2 2010
But if I instead use WHERE:
(BTK_CLOSED_DATE < #TheMonthLastDate OR
TSK_START_DATE < #TheMonthLastDate
)
then I see:
r2 r3 MonthClosed YearClosed
NULL 2010-10-01 00:00:00.000 10 2010
NULL 2010-09-01 00:00:00.000 9 2010
NULL 2010-09-01 00:00:00.000 9 2010
NULL 2010-08-01 00:00:00.000 8 2010
NULL 2010-08-01 00:00:00.000 8 2010
...
So notice that in first result I see NULL for June 2010, which is what I want.
I think the problem has something to do with the fact that my data contains 2009-2011 data, but I only compare months and not years. How would I add in this additional logic?
The only place where you are reducing the data is with the WHERE clause you have already identified. Therefore, the reason you are not getting all the months you expect is down to the column TSK_START_DATE not being less than #TheMonthLastDate for all months.
To prove this hypothesis, run the following section of your query (I have commented out part of the where clause and removed everything under 'yourTable' cte). The results should show you what is being returned in the TSK_Start_Date column for your missing months and help you identify why the rows are missing when applying the < #TheMonthLastDate clause.
DECLARE #END_YEAR VARCHAR(10)
DECLARE #END_MONTH VARCHAR(10)
SET #END_YEAR = '2010'
SET #END_MONTH = '10'
DECLARE #TheMonthLastDate DATETIME
DECLARE #TempDate DATETIME
SET #TempDate = '2010-11-01 00:00:00.000'
SET #TheMonthLastDate = '2010-11-01 00:00:00.000'
;with months
as
(
select dateadd(month, -1, dateadd(day, datediff(day, 0, #TempDate), 0)) as m
union all
select dateadd(month, -1, m)
from months
where m > dateadd(month, -12, #TempDate)
)
,yourTable(DateOpened, DateClosed)
as
(select TSK_START_DATE, BTK_CLOSED_DATE
FROM [PROC].ALL_AUDIT
WHERE
(BTK_CLOSED_DATE < #TheMonthLastDate OR
--TSK_START_DATE < #TheMonthLastDate
)
)
select * , #TheMonthLastDate TheMonthLastDate from yourTable