How to count amount of data for each row - sql

I have this table:
ID Name 01 02 03 04 05 06 07
0000068 Name1 V VX
0000069 Name2 V VX VX V V
0000070 Name3 V V V V V V
This is an table for absence check and I want to count the amount of data from each row from column 01 to 07, so I expect the first row will give result of 2, second row 5, and third row 6. And if possible I want that result to be added as a new column. Is there a way to work this somehow?

If it's always V or VX you could replace the VX with V, concatenate
them together and take the LEN():
SELECT *, LEN(REPLACE([01]+[02]+[03]+[04]+[05]+[06]+[07],'X','')) AS New_Ct
FROM YourTable
If the blanks are actually NULL you'd have to wrap them in ISNULL():
SELECT *, LEN(REPLACE(ISNULL([01],'')+ISNULL([02],'')+ISNULL([03],'')+ISNULL([04],'')+ISNULL([05],'')+ISNULL([06],'')+ISNULL([07],''),'X','')) AS New_Ct
FROM Table1
Demo: SQL Fiddle

If the number of columns is static, you can use a simple CASE expression.
SELECT *,
CASE WHEN [01] = '' OR [01] IS NULL THEN 0 ELSE 1 END +
CASE WHEN [02] = '' OR [02] IS NULL THEN 0 ELSE 1 END +
CASE WHEN [03] = '' OR [03] IS NULL THEN 0 ELSE 1 END +
CASE WHEN [04] = '' OR [04] IS NULL THEN 0 ELSE 1 END +
CASE WHEN [05] = '' OR [05] IS NULL THEN 0 ELSE 1 END +
CASE WHEN [06] = '' OR [06] IS NULL THEN 0 ELSE 1 END +
CASE WHEN [07] = '' OR [07] IS NULL THEN 0 ELSE 1 END [cnt]
FROM Table1;
An SQLfiddle to test with.

SELECT 01+02+03+04+05+06+07 AS total_number FROM table_name;

Try Like this
SELECT ID,Name,
(Case When[01] IS Null or [01] = '' then 0 else 1 end) +
(Case When[02] IS Null or [02] = '' then 0 else 1 end) +
(Case When[03] IS Null or [03] = '' then 0 else 1 end) +
(Case When[04] IS Null or [04] = '' then 0 else 1 end) +
(Case When[05] IS Null or [05] = '' then 0 else 1 end) +
(Case When[06] IS Null or [06] = '' then 0 else 1 end) +
(Case When[07] IS Null or [07] = '' then 0 else 1 end) AS Total
FROM table1;
FIDDLE DEMO

Related

How to get output to not write more SQL CASES using select query

I have below xyz table data
id ADivision BDivision CDivision DDivision EDivision FDivision
1 0 1 0 0 1 0
2 1 1 0 0 1 1
I want output like below
id Divisions
1 B-E
2 A-B-E-F
I tried by using switch case but need to write more cases
any other ways to get output
The CONCAT_WS() function is your friend here:
SELECT
id,
CONCAT_WS('-', CASE WHEN ADivision = 1 THEN 'A' END,
CASE WHEN BDivision = 1 THEN 'B' END,
CASE WHEN CDivision = 1 THEN 'C' END,
CASE WHEN DDivision = 1 THEN 'D' END,
CASE WHEN EDivision = 1 THEN 'E' END,
CASE WHEN FDivision = 1 THEN 'F' END) AS Divisions
FROM yourTable
ORDER BY id;
Here is a workaround for earlier versions of SQL Server which might not support CONCAT_WS():
SELECT
id,
STUFF(
COALESCE('-' + CASE WHEN ADivision = 1 THEN 'A' END, '') +
COALESCE('-' + CASE WHEN BDivision = 1 THEN 'B' END, '') +
COALESCE('-' + CASE WHEN CDivision = 1 THEN 'C' END, '') +
COALESCE('-' + CASE WHEN DDivision = 1 THEN 'D' END, '') +
COALESCE('-' + CASE WHEN EDivision = 1 THEN 'E' END, '') +
COALESCE('-' + CASE WHEN FDivision = 1 THEN 'F' END, '')
1, 2, '') AS Divisions
FROM yourTable
ORDER BY id;

sql get total of value across multiple columns

I have a sql server 2012 db with a table with 10 columns
name test1, test2, test3, test4,....
bob yes no null yes
john no yes yes null
I want to get a total of all results from the 'test' fields so i want my results to be
yes = 4
no = 2
null = 2
I have tried using cte, sum, case when but I cant get the results i'm looking for. below is a sample of my sql if anyone could tell me how to go about getting the results i'm looking for.
with cte as
(
SELECT
test1,
sum (case when test1 = 'yes' then 1 else 0 end) as yes,
sum (case when test1= 'no' then 1 else 0 end) as no,
sum (case when test1 is null then 1 else 0 end) as notset
from names
group by Inspection1Type)
select
sum (yes) as 'yes',
sum(no) as 'no'
sum(notset) as 'Not Set'
from cte;
it works for the first column but not for the remaining ones as i'm looking for same value it complains about my aliases being the same
Try this cut&paste approach:
SELECT
sum (case when test1 = 'yes' then 1 else 0 end
+case when test2 = 'yes' then 1 else 0 end
+case when test3 = 'yes' then 1 else 0 end
...
+case when test10 = 'yes' then 1 else 0 end) as yes,
sum (case when test1 = 'no' then 1 else 0 end
+case when test2 = 'no' then 1 else 0 end
+case when test3 = 'no' then 1 else 0 end
...
+case when test10 = 'no' then 1 else 0 end) as no,
sum (case when test1 is null then 1 else 0 end
+case when test2 is null then 1 else 0 end
+case when test3 is null then 1 else 0 end
...
+case when test10 is null then 1 else 0 end) as notset
from names
I like handling this with apply. If you want one row per name:
select n.*, v.*
from names n cross apply
(select sum(case when v.test = 'yes' then 1 else 0 end) as yes,
sum(case when v.test = 'no' then 1 else 0 end) as no,
sum(case when v.test is null then 1 else 0 end) as nulls
from (values (n.test1), (n.test2), . . . (n.test10)) v(test)
) v;
If you want one row for all the data:
select sum(case when v.test = 'yes' then 1 else 0 end) as yes,
sum(case when v.test = 'no' then 1 else 0 end) as no,
sum(case when v.test is null then 1 else 0 end) as nulls
from names n cross apply
(values (n.test1), (n.test2), . . . (n.test10)) v(test);
Having repeating columns in a table is usually a sign of an issue with the data model. Normally, you would want one row per name/test, and that would simplify queries on this data.
Try this:
WITH ABC
as
(
SELECT 'bob' as name, 'yes' as test1, 'no' as test2, null as test3, 'yes' as test4
UNION ALL
SELECT 'john', 'no','yes','yes',null
)
SELECT SUM(CASE WHEN A.result = 'yes' then 1 else 0 end) as [Yes],
SUM(CASE WHEN A.result = 'no' then 1 else 0 end) as [No],
SUM(CASE WHEN A.result is null then 1 else 0 end) as [Null]
FROM
(
SELECT name,result
FROM ABC
CROSS APPLY(VALUES(test1),(test2),(test3),(test4)) --may add up to test10
COLUMNNAMES(result)
) as A

Counting columns with a where clause

Is there a way to count a number of columns which has a particular value for each rows in Hive.
I have data which looks like in input and I want to count how many columns have value 'a' and how many column have value 'b' and get the output like in 'Output'.
Is there a way to accomplish this with Hive query?
One method in Hive is:
select ( (case when cl_1 = 'a' then 1 else 0 end) +
(case when cl_2 = 'a' then 1 else 0 end) +
(case when cl_3 = 'a' then 1 else 0 end) +
(case when cl_4 = 'a' then 1 else 0 end) +
(case when cl_5 = 'a' then 1 else 0 end)
) as count_a,
( (case when cl_1 = 'b' then 1 else 0 end) +
(case when cl_2 = 'b' then 1 else 0 end) +
(case when cl_3 = 'b' then 1 else 0 end) +
(case when cl_4 = 'b' then 1 else 0 end) +
(case when cl_5 = 'b' then 1 else 0 end)
) as count_b
from t;
To get the total count, I would suggest using a subquery and adding count_a and count_b.
Use lateral view with explode on the data and do the aggregations on it.
select id
,sum(cast(col='a' as int)) as cnt_a
,sum(cast(col='b' as int)) as cnt_b
,sum(cast(col in ('a','b') as int)) as cnt_total
from tbl
lateral view explode(array(ci_1,ci_2,ci_3,ci_4,ci_5)) tbl as col
group by id

Create and classify a row based on column values

I am attempting to assign a classification to a row of data based on whether certain values exist. Utilizing the sample code below I have gotten to a place where I've gotten stuck.
proc sql;
create table test
(id char(4),
task char(4),
id2 char(4),
status char(10),
seconds num);
insert into test
values('1','A','1','COMP',15)
values('1','B','2','WORK',20)
values('1','C','3','COMP',50)
values('1','D','3','COMP',null)
values('2','A','1','COMP',15)
values('2','B','2','COMP',520)
values('2','C','2','COMP',NULL)
values('2','D','3','COMP',221)
values('2','E','3','COMP',null)
values('2','F','3','COMP',null);
proc sql;
create table test2 as
select
ID,
ID2,
STATUS,
SUM(SECONDS) AS SECONDS,
sum(case when task='A' THEN 1 ELSE 0 END) AS A,
sum(case when task='B' THEN 1 ELSE 0 END) AS B,
sum(case when task='C' THEN 1 ELSE 0 END) AS C,
sum(case when task='D' THEN 1 ELSE 0 END) AS D,
sum(case when task='E' THEN 1 ELSE 0 END) AS E,
sum(case when task='F' THEN 1 ELSE 0 END) AS F
from
test
GROUP BY
ID,
ID2,
STATUS
;
quit;
Ultimately I would like to classify each row that gets created in the second step 'test2' to have a column that looks to the values in each lettered column(A-F) and Label them as such. So when the Row has a 1 in Column A only, it would be labeled 'A' but when a row has a 1 in multiple columns like 'D', 'E' and 'F' I would like it to be labeled as D_E_F.
Best way to do this is in a DATA STEP:
data test3;
format classifier $32.;
set test2;
array vars[6] A B C D E F;
classifier = "";
do i=1 to 6;
if vars[i] then
classifier = catx("_",classifier,vname(vars[i]));
end;
drop i;
run;
I create a character variable CLASSIFIER with length 32.
I define an array that groups the columns A through F. This allows me to loop over those columns easily.
Initialize the CLASSIFIER variable.
Loop over the array. If the value =1, then add the name of the variable to the CLASSIFIER string.
CATX(delim,str1,str2) concatenates str1 and str2 with the delim in the middle. It also removes whitespace.
VNAME(array[i]) returns the variable name of the variable pointed to by array[i].
Finally remove the i loop variable, unless you really want it in your output.
I know it is ugly, but you can do it with CASE statements accumulating the wanted result in another field. You have the SQL Fiddle here.
Note that if it is possible that the concatenation is empty you will have to check this condition to avoid performing the substring.
select
ID,
ID2,
STATUS,
SUM(SECONDS) AS SECONDS,
sum(case when task='A' THEN 1 ELSE 0 END) AS A,
sum(case when task='B' THEN 1 ELSE 0 END) AS B,
sum(case when task='C' THEN 1 ELSE 0 END) AS C,
sum(case when task='D' THEN 1 ELSE 0 END) AS D,
sum(case when task='E' THEN 1 ELSE 0 END) AS E,
sum(case when task='F' THEN 1 ELSE 0 END) AS F,
substring(
case when sum(case when task='A' THEN 1 ELSE 0 END) = 1 then '_A' else '' end
+ case when sum(case when task='B' THEN 1 ELSE 0 END) = 1 then '_B' else '' end
+ case when sum(case when task='C' THEN 1 ELSE 0 END) = 1 then '_C' else '' end
+ case when sum(case when task='D' THEN 1 ELSE 0 END) = 1 then '_D' else '' end
+ case when sum(case when task='E' THEN 1 ELSE 0 END) = 1 then '_E' else '' end
+ case when sum(case when task='F' THEN 1 ELSE 0 END) = 1 then '_F' else '' end,
2, len(case when sum(case when task='A' THEN 1 ELSE 0 END) = 1 then '_A' else '' end
+ case when sum(case when task='B' THEN 1 ELSE 0 END) = 1 then '_B' else '' end
+ case when sum(case when task='C' THEN 1 ELSE 0 END) = 1 then '_C' else '' end
+ case when sum(case when task='D' THEN 1 ELSE 0 END) = 1 then '_D' else '' end
+ case when sum(case when task='E' THEN 1 ELSE 0 END) = 1 then '_E' else '' end
+ case when sum(case when task='F' THEN 1 ELSE 0 END) = 1 then '_F' else '' end) - 1) as wantedOutput
from
test
GROUP BY
ID,
ID2,
STATUS

how to get field name what are the field have value?

i have one table sql server like below , from that table i want to get quesno, field name[what are the field have value]
QuesNo A B C D
1 1 0 1 0
2 0 0 0 1
Output :
QuesNo Result
1 A,C
2 D
Is there any possible ways to get outpu?
This ought to do it...
SELECT QuesNo, SUBSTRING(Answers, 1, LENGTH(Answers) - 1) AS Answers
FROM (
SELECT QuesNo,
CASE
WHEN A <> 0 THEN 'A,'
ELSE ''
END +
CASE
WHEN B <> 0 THEN 'B,'
ELSE ''
END +
CASE
WHEN C <> 0 THEN 'C,'
ELSE ''
END +
CASE
WHEN D <> 0 THEN 'D,'
ELSE ''
END AS Answers
FROM yourtable
) Foo