Creating extra columns based on condition (Case When Sum) - sql

I have survey table where someone is asked roughly 5 questions. 4 of those questions are the same questions, but the options to their answers are different since they were to understand their purchase.
Here are the questions:
ID Question qid Answer
101005 what brands did you purchase the past 5 months 1 Coca-Cola or Pepsi or Dr.Pepper
101005 what brands did you purchase the past 5 months 1 Dr.Pepper
101005 what brands did you purchase the past 5 months 1 store brand
101005 what brands did you purchase the past 5 months 1 Coca-Cola
101005 how many people live in your house 4 4
101005 what is your prefer retailers 8 walmart
The goal is to create four extra columns based on their answer and they will be assigned a 1 or 0. Since this person's answer is coca cola, I want to assign them in the column of current_buyer and give them 1 and 0 will be new_buyer column. I also want to make sure that even though he answer Dr.Pepper in the second row, it still recognizes him as a current_buyer. In the same breath I want to assign this person a 1 in the 3rd column as a drinker and 0 4th column in prospect.
Here is how the table should look like
ID Question qid answer Current_buyer New_buyer drinker prospect
101005 what brands did you purchase the past 5 months 1 Coca-Cola or Pepsi or Dr.Pepper 1 0 1 0
101005 what brands did you purchase the past 5 months 1 Dr.Pepper 1 0 1 0
101005 how many people live in your house 4 4 1 0 1 0
The goal is to see if ID bought coca-cola the past 5 months, they are a current buyer (1) and drinker (1) and will have (0) for new_buyer and prospect in their entire profile.
Here is the code that I try:
select ID,qid,question,answer,s_date,
Case when Sum(Case when [answer] like'%coca-cola%' then 1 else 0 end)>=1 then 1
else 0 end current_buyer
,Case when Sum(Case when [answer] like'%coca-cola%' then 1 else 0 end)=0 then 1
else 0 end New_buyer
,Case when Sum(Case when [answer] like'%coca-cola,Dr.pepper,pepsi%' then 1 else 0 end)>=1 then 1
else 0 end drinker
,Case when Sum(Case when [answer] like'%coca-cola,Dr.pepper,pepsi%' then 1 else 0 end)=0 then 1
else 0 end Prospect
Unfortunately, using this code I'm getting 0 in the drinker column even though people selected coca-cola. Any help would be appreciated.

I'm not 100% sure that I understand the logic behind assigning the various values, but in general it seems that you are assigning the value based on an aggregation of multiple rows. Therefore you need to do the aggregation first (in this case in a CTE) and then join back to that for your query.
Also worth noting is that even though your are doing your matching with a LIKE operator - everything between the [%] characters will need to match exactly somewhere in your [answer]. I don't think that this is what you want - so I've split them out. However I'm not 100% sure if I've got the logical operators completely correct.
Do you need something like:
;with analysisCTE as (select ID,qid,
Case when Sum(Case when [answer] like'%coca-cola%' then 1 else 0 end)>=1 then 1
else 0 end current_buyer
,Case when Sum(Case when [answer] like'%coca-cola%' then 1 else 0 end)=0 then 1
else 0 end New_buyer
,Case when Sum(Case when [answer] like'%coca-cola%' OR [answer] like '%Dr.pepper%' OR [answer] like '%pepsi%' then 1 else 0 end)>=1 then 1
else 0 end drinker
,Case when Sum(Case when [answer] like'%coca-cola%' OR [answer] like '%Dr.pepper%' OR [answer] like '%pepsi%' then 1 else 0 end)=0 then 1
else 0 end Prospect
from drinks
group by id, qid)
select d.ID,d.qid,d.question,d.answer, a.current_buyer, a.New_buyer, a.drinker, a.Prospect
from drinks d
inner join analysisCTE a on d.id = a.id and d.qid = a.qid

Related

SQL: SUM OR COUNT with CASE WHEN condition in multiple criteria

Course name
Section number
Course type
MATH 101
1
In person
MATH 101
2
In person
MATH 101
3
Online
MATH 101
4
In person
SOC 101
1
In person
SOC 101
2
In person
SOC 101
3
In person
ENGL 201
1
In person
ENGL 201
2
Online
ENGL 201
3
Online
ENGL 201
4
In person
PHY 101
1
Online
PHY 101
2
Online
From this table, I'd like to count Courses with only an 'In person' course, an 'Online' course, and both course types.
The query I tried is below.
SELECT
SUM(CASE WHEN coursetype = 'Inperson' AND coursetype = 'Online' THEN 1 ELSE 0 END) AS bothtype,
SUM(CASE WHEN coursetype = 'Online' THEN 1 ELSE 0 END) AS Onlineonly,
SUM(CASE WHEN coursetype = 'Inperson' THEN 1 ELSE 0 END) AS Onlineonly
From Course
The result what I expected is
bothtpye
Onlineonly
Inpersononly
2
1
1
but I got
bothtpye
Onlineonly
Inpersononly
0
7
6
Please advise me to get through this.
Thank you.
My solution uses double conditional aggregation.
SELECT SUM (CASE WHEN In_Person > 0 AND Online > 0 THEN 1 ELSE 0 END) as bothtype,
SUM (CASE WHEN In_Person > 0 AND Online = 0 THEN 1 ELSE 0 END) as inpersononly,
SUM (CASE WHEN In_Person = 0 AND Online > 0 THEN 1 ELSE 0 END) as onlineonly
FROM (
SELECT Course_name,
SUM(CASE WHEN Course_type='In Person' THEN 1 ELSE 0 END) as In_Person,
SUM(CASE WHEN Course_type='Online' THEN 1 ELSE 0 END) as Online
FROM Course
GROUP BY Course_name
) tot
DEMO Fiddle
SUGGESTION ( using PL/SQL ! ) :
CREATE PROCEDURE countCourses(OUT bothtype INT,OUT Inpersononly INT,OUT Onlineonly INT)
begin
SELECT COUNT(*) INTO bothtype FROM Course;
select COUNT(*) INTO Inpersononly FROM Course
WHERE courseType = "In person";
select COUNT(*) INTO Onlineonly FROM Course
WHERE courseType = "Online";
end;
call countCourses(#bothtype,#Inpersononly,#Onlineonly);
SELECT #bothtype,#Inpersononly,#Onlineonly;
EXPLICATION :
Creating procedure to store the count of each type of course in OUT variable
Call the procedure with convenient parameters
Select out given parameters

SQL transform table with sum based on values

i have table like this:
operation_id
order_id
qty
qty_type
detail_type
1
1
240
ready
glued
1
1
199
ready
unglued
1
1
100
done
glued
1
2
50
ready
glued
and would like to transform into this. it means to add 4 columns and to sum them from above table based on a conditions, like detail_type = 'glued', qty_type = 'ready' etc.
operation_id
order_id
qty_glued_ready
qty_unglued_ready
qty_glued_done
qty_unglued_done
1
1
240
199
10
10
can somebody help me how query should look like?
I assume it is just an example that you have mentioned in your OP and it is not accurate according to your table data you have mentioned.
I don't understand how your qty_glued_done is 10
But here is something you can start working out with:
SELECT o.`operation_id`, o.`order_id`,
SUM(CASE WHEN `detail_type`='glued' AND o.`qty_type`='ready' THEN o.`qty` ELSE 0 END) AS qty_glued_ready,
SUM(CASE WHEN `detail_type`='unglued' AND o.`qty_type`='ready' THEN o.`qty` ELSE 0 END) AS qty_unglued_ready
(and so on)
FROM `operation_table` o GROUP BY o.`operation_id`

create total accordif if column is filled

I want to count the number of total people who will attend to an event and this number is calculated by the person who invites and how many people will be invited.
So I have this info,
refInqCredLink RegisterDate Name Phone Email Horario Insc1 Insc2 Insc3
496 2019-08-29 15:38:13.183 Abilio 91 abilio#hotmail.com 3 albano jorge
497 2019-08-30 14:12:46.873 Duarte 25 duarte#sapo.pt 3 antonio
499 2019-08-30 14:48:29.067 AGOSTINHO 92 agostinho#gmail.com 1 Jorge Antonio Manuel Fernando
In this case "John" will attend the event and will invite "albano" and "jorge". So the total number of people in this line is 3.
I need to check if Insc1, Insc2 and Insc3 column have value and if so (<>'') count as 1 person. I need to create a view based in this table with this sum.
If I try this code,
Select
SUM(case when not Name is null then 1 else 0 end
+
case when not Insc1 is null then 1 else 0 end
+
case when not Insc2 is null then 1 else 0 end
+
case when not Insc3 is null then 1 else 0 end)
from LACTINFO_InquiryCredential_Link_Seminario
this returns 12 instead of 8.
I have 3 Names + 5 Invitees = 8
Try the following
Select
SUM(case when Insc1 is null or Insc1 = '' then 0 else 1 end
+
case when Insc2 is null or Insc2 = '' then 0 else 1 end
+
case when Insc3 is null or Insc3 = '' then 0 else 1 end)
+
count(*)
from tab
To get the total, you can use count():
select count(*) + -- everyone is counted once
count(insc1) + count(insc2) + count(insc3) -- additional invitees
from t;
First, note that this is a poor data model. You should have a separate table with one row per person invited.
Second, the same person could be invited multiple times. This formulation does not take that into account. Using just first names makes it hard to deduplicate the data.

SQL rows to column [duplicate]

This question already has answers here:
SQL Rows to Columns
(3 answers)
Closed 7 years ago.
This is my query.
select name, walk_to, count(*) count
from walk
where name='Rizwan'
group by name, walk_t0;
This results in data like:
NAME WALK_TO COUNT
Rizwan Cafe 2
Rizwan Arena 10
Rizwan Outside 20
There are other users' data as well. What I want is:
NAME CAFE ARENA OUTSIDE
Rizwan 2 10 20
John 3 21 90
James 5 5 9
Any idea how to write a query to get this result?
SELECT name,
SUM(CASE WHEN walk_to = 'Cafe' THEN 1 ELSE 0 END) Cafe,
SUM(CASE WHEN walk_to = 'Arena' THEN 1 ELSE 0 END) Arena,
SUM(CASE WHEN walk_to = 'Outside' THEN 1 ELSE 0 END) Outside
FROM walk
GROUP BY name
This is called pivioting for more examples look here SQL Server: Examples of PIVOTing String data
select name,
sum(case when walk_to='Cafe' then 1 else 0 end) as CAFE,
sum(case when walk_to='Arena' then 1 else 0 end) as ARENA,
sum(case when walk_to='Outside' then 1 else 0 end) as OUTSIDE
FROM walk
GROUP BY name

How to apply answer key on students' responses

I conducted a MCQs type test for students in Eng, math, and science
Students solved their test on a sheet readable by the OMR/OCR.
The machine produced responses of the students in follwoig way:-
Student ID Subject Q1 Q2 Q3 Q4 ......
201 English 3 1 4 1 ......
201 Math 3 2 1 1 ....
201 Science 2 1 2 3 ....
202 English 3 1 4 1 ......
202 Math 3 2 1 1 ....
202 Science 2 1 2 3 ....
-
-
-
How can i apply answer key on this data e.g for English my answer key is:
2 2 4 1 .....
would you pleas suggest a query for this situation
SELECT
StudentId
,CASE WHEN Q2 = ?ANSWER? then 1 ELSE 0 END
,CASE WHEN Q3 = ?ANSWER? then 1 ELSE 0 END
,CASE WHEN Q4 = ?ANSWER? then 1 ELSE 0 END
,CASE WHEN Q5 = ?ANSWER? then 1 ELSE 0 END
FROM
Table
Where subject = 'English'
One of possible solutions replace ?ANSWER? with something from your answer key
Other would be to generate tables like:
CREATE TABLE EnglishKey(
QuestionId int,
Answer int)
Then insert your values in this way:
INSERT INTO EnglishKey VALUES (1,3),(2,4),(....)
Replacing 1 with question number and answer with proper answer.
And then creating a SELECT should be easy
SELECT
a.StudentID
CASE WHEN a.Q1 <> a.A1 THEN 0 ELSE 1 end AS Result1,
CASE WHEN a.Q2 <> a.A2 THEN 0 ELSE 1 end AS Result2,
CASE WHEN a.Q3 <> a.A3 THEN 0 ELSE 1 end AS Result3,
CASE WHEN a.Q4 <> a.A4 THEN 0 ELSE 1 end AS Result4,
CASE WHEN a.Q5 <> a.A5 THEN 0 ELSE 1 end AS Result5,
CASE WHEN a.Q6 <> a.A6 THEN 0 ELSE 1 end AS Result6,
CASE WHEN a.Q7 <> a.A7 THEN 0 ELSE 1 end AS Result7,
CASE WHEN a.Q8 <> a.A8 THEN 0 ELSE 1 end AS Result8
FROM
StudentTable a
INNER JOIN AnswerTable b ON a.[SUBJECT] = b.[SUBJECT]
This answer presumes that you have the answers in a seperate table and can join on subject.
If you find it a pain to write out all the case statements (could have 100s of questions) you can quickly build these queries in Microsoft Excel or open office by breaking up the statement across multiple columns, have it fill in the 1,2,3,4s etc and then copy paste once happy.