Using an AND statement in a CASE in t sql - tsql

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

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

Get email frequency using grouping sets

I have a table with emails logs and need to check the email frequency. using grouping sets retrieve email count hourly, daily, weekly, monthly and yearly.
Can anyone send me an example.
Thank you !
SELECT DATEPART(yyyy,create_time) [year]
, DATEPART(mm,create_time) [month]
, DATEPART(WEEK,create_time) [week]
, DATEPART(dd,create_time) [day]
, DATEPART(hour,create_time) [hour]
, COUNT(*) AS c
FROM your_table
GROUP BY GROUPING SETS (DATEPART(yyyy,create_time)
,DATEPART(mm,create_time)
,DATEPART(WEEK,create_time)
,DATEPART(dd,create_time)
,DATEPART(hour,create_time))
ORDER BY [year], [month], [week], [day], [hour]
To group by multiple fields, just group columns in parentheses:
,(DATEPART(yyyy,create_time), DATEPART(mm,create_time))
Here's sample output, including the year/month grouping:
year month week day hour c
NULL NULL NULL NULL 0 12
NULL NULL NULL NULL 1 1
NULL NULL NULL 1 NULL 219
NULL NULL NULL 2 NULL 467
NULL NULL 1 NULL NULL 124
NULL NULL 2 NULL NULL 216
NULL 1 NULL NULL NULL 1899
NULL 2 NULL NULL NULL 1419
2015 NULL NULL NULL NULL 3750
2016 NULL NULL NULL NULL 7446
2015 8 NULL NULL NULL 391
2015 9 NULL NULL NULL 891
Thank you for the reply !
I have added ID column to the grouping sets,not getting if it is Hourly/weekly/daily/monthly generated.
SELECT ID, DATEPART(yyyy,create_time) [year]
, DATEPART(mm,create_time) [month]
, DATEPART(WEEK,create_time) [week]
, DATEPART(dd,create_time) [day]
, DATEPART(hour,create_time) [hour]
, COUNT(*) AS c
FROM your_table
GROUP BY GROUPING SETS(
(DATEPART(yyyy,create_time),ID)
,(DATEPART(mm,create_time),ID)
,(DATEPART(WEEK,create_time),ID)
,(DATEPART(dd,create_time),ID)
,(DATEPART(hour,create_time) ,ID))
ORDER BY [year], [month], [week], [day], [hour],ID
Result
Month Week Daily Hour C
NULL NULL NULL 0 12
NULL NULL NULL 0 471
NULL NULL NULL 0 176
NULL NULL NULL 0 145
NULL NULL NULL 0 633
NULL NULL NULL 0 13
NULL NULL NULL 0 24
NULL NULL NULL 0 2
NULL NULL NULL 0 324
NULL NULL NULL 0 555

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

Ignore null values when using SQL Server 2012's Last_Value() function

I am using SQL Server 2012 and have a table of values that look like this. It is populated with event data.
FldType Date Price Size
--------------------------------------------
2 2012-08-22 00:02:01 9140 1048
0 2012-08-22 00:02:02 9140 77
1 2012-08-22 00:02:03 9150 281
2 2012-08-22 00:02:04 9140 1090
0 2012-08-22 00:02:05 9150 1
1 2012-08-22 00:02:06 9150 324
2 2012-08-22 00:02:07 9140 1063
I would like to track the lastest value for each of the 3 field types (0,1,2) so that the final output looks like this.
Date Price0 Size0 Price1 Size1 Price2 Size2
-----------------------------------------------------------------
2012-08-22 00:02:01 NULL NULL NULL NULL 9140 1048
2012-08-22 00:02:02 9140 77 NULL NULL 9140 1048
2012-08-22 00:02:03 9140 77 9150 281 9140 1048
2012-08-22 00:02:04 9140 77 9150 281 9140 1090
2012-08-22 00:02:05 9150 1 9150 281 9140 1090
2012-08-22 00:02:06 9150 1 9150 324 9140 1090
2012-08-22 00:02:07 9150 1 9150 324 9140 1063
Unfortunately, it is not ignoring subsequent null values so I get this instead.
Date Price0 Size0 Price1 Size1 Price2 Size2
-----------------------------------------------------------------
2012-08-22 00:02:01 NULL NULL NULL NULL 9140 1048
2012-08-22 00:02:02 9140 77 NULL NULL NULL NULL
2012-08-22 00:02:03 NULL NULL 9150 281 NULL NULL
2012-08-22 00:02:04 NULL NULL NULL NULL 9140 1090
2012-08-22 00:02:05 9150 1 NULL NULL NULL NULL
2012-08-22 00:02:06 NULL NULL 9150 324 NULL NULL
2012-08-22 00:02:07 NULL NULL NULL NULL 9140 1063
My current query looks like this
SELECT [Date],
LAST_VALUE(Price0) OVER (PARTITION BY FldType ORDER BY [Date] ) AS Price0,
LAST_VALUE(Size0) OVER (PARTITION BY FldType ORDER BY [Date]) AS Size0,
LAST_VALUE(Price1) OVER (PARTITION BY FldType ORDER BY [Date] ) AS Price1,
LAST_VALUE(Size1) OVER (PARTITION BY FldType ORDER BY [Date]) AS Size1,
LAST_VALUE(Price2) OVER (PARTITION BY FldType ORDER BY [Date] ) AS Price2,
LAST_VALUE(Size2) OVER (PARTITION BY FldType ORDER BY [Date]) AS Size2
FROM (
SELECT FldType, [Date], Price, Size,
CASE WHEN FldType = 0 THEN Price END as Price0,
CASE WHEN FldType = 0 THEN Size END as Size0,
CASE WHEN FldType = 1 THEN Price END as Price1,
CASE WHEN FldType = 1 THEN Size END as Size1,
CASE WHEN FldType = 2 THEN Price END as Price2,
CASE WHEN FldType = 2 THEN Size END as Size2
FROM [RawData].[dbo].[Events]
) as T1
ORDER BY [Date]
Is there some way to have SQL Server 2012 ignore null values when determining the lastest value? Or is there a better approach not using Last_Value() function?
To summarize I am trying to achieve two thing.
Split the Price and Size columns into 6 columns (2 columns x 3 field types)
Keep track of the latest value in each of these columns.
Any suggestions would be apprciated.
I'm not sure you can do it with LAST_VALUE, unless you add a PIVOT maybe.
Also, you need to treat Size and Price separately because they come from different rows. So, this achieves what you want be breaking it down.
DECLARE #source TABLE (FldType int, DateCol DateTime, Price int, Size int);
INSERT #source VALUES
(2, '2012-08-22 00:02:01', 9140, 1048),(0, '2012-08-22 00:02:02', 9140, 77),
(1, '2012-08-22 00:02:03', 9150, 281),(2, '2012-08-22 00:02:04', 9140, 1090),
(0, '2012-08-22 00:02:05', 9150, 1),(1, '2012-08-22 00:02:06', 9150, 324),
(2, '2012-08-22 00:02:07', 9140, 1063);
SELECT
S.DateCol, Xp0.Price0, Xs0.Size0, Xp1.Price1, Xs1.Size1, Xp2.Price2, Xs2.Size2
FROM
#source S
OUTER APPLY
(SELECT TOP 1 S0.Price AS Price0 FROM #source S0 WHERE S0.FldType = 0 AND S0.DateCol <= S.DateCol ORDER BY S0.DateCol DESC) Xp0
OUTER APPLY
(SELECT TOP 1 S1.Price AS Price1 FROM #source S1 WHERE S1.FldType = 1 AND S1.DateCol <= S.DateCol ORDER BY S1.DateCol DESC) Xp1
OUTER APPLY
(SELECT TOP 1 S2.Price AS Price2 FROM #source S2 WHERE S2.FldType = 2 AND S2.DateCol <= S.DateCol ORDER BY S2.DateCol DESC) Xp2
OUTER APPLY
(SELECT TOP 1 S0.Size AS Size0 FROM #source S0 WHERE S0.FldType = 0 AND S0.DateCol <= S.DateCol ORDER BY S0.DateCol DESC) Xs0
OUTER APPLY
(SELECT TOP 1 S1.Size AS Size1 FROM #source S1 WHERE S1.FldType = 1 AND S1.DateCol <= S.DateCol ORDER BY S1.DateCol DESC) Xs1
OUTER APPLY
(SELECT TOP 1 S2.Size AS Size2 FROM #source S2 WHERE S2.FldType = 2 AND S2.DateCol <= S.DateCol ORDER BY S2.DateCol DESC) Xs2
ORDER BY
DateCol;
The other way is to maintain a separate table via triggers or some ETL that does it the summary for you.

Tsql unique records grouping

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