How do i count null values while making cross tab query?
I have a table with three colums [id, name, answer]
i have following records:
ID NAME ANS
1 ABC 1
1 ABC 0
1 ABC NULL
2 XYZ 1
2 XYZ NULL
2 XYZ NULL
2 XYZ 1
2 XYZ 0
1 ABC 0
now i would like to get my result:
ID Name NULLCOUNT TRUE COUNT FALSE COUNT
1 ABC 1 1 2
2 XYZ 2 2 1
I am using following SQL Statement:
select ID, NAME,
sum(case ANS when null then 1 else 0 end) as NULLCOUNT,
sum(case ANS when 1 then 1 else 0 end) as TRUECOUNT,
sum(case ANS when 0 then 1 else 0 end) as FALSECOUNT
from
TBL1
Group By ID, Name
Getting my result:
ID Name NULLCOUNT TRUE COUNT FALSE COUNT
1 ABC 0 1 2
2 XYZ 0 2 1
The NULL Count is getting error. Why and how can i solve this?
I believe instead of this:
sum(case ANS when null then 1 else 0 end) as NULLCOUNT
You should use this:
sum(case when ANS is null then 1 else 0 end) as NULLCOUNT
null -> is null?
NULL doesn't even compare with itself, you could use "CASE WHEN ANS is NULL"(you're also missing GROUP BY). Or try:
select ID, NAME,
sum(if(ans IS NULL, 1, 0)) as NULLCOUNT,
sum(case ANS when 1 then 1 else 0 end) as TRUECOUNT,
sum(case ANS when 0 then 1 else 0 end) as FALSECOUNT
from
TBL1
group by ID,NAME
Related
I have BIGINT column in my Redshift table, and I want a query that will:
Count how many times the value '1' appears in each bit position across the binary value in all the rows of this column
Will show it in a way that I'll be able to take the x top bits_positions.
For example (I'm already writing the integer values as binary to simplify the example):
column
--------
11011110 = 222
00000000 = 0
11111100 = 252
00011000 = 24
11111100 = 252
00011000 = 24
11000010 = 194
76543210 <- bit_position
will return a table like:
bit_position count
0 0
1 2
2 3
3 5
4 5
5 2
6 4
7 4
In this case I'll be able to get the top five bit_position: (3,4,6,7,2)
Note: I'll might have up to 64 bit_positions for a column.
You can use a bit-wise AND & to check for each position.
Here's an example going across rows:
SELECT SUM(CASE WHEN bit_col & 64 > 0 THEN 1 ELSE 0 END) "1000000"
, SUM(CASE WHEN bit_col & 32 > 0 THEN 1 ELSE 0 END) "0100000"
, SUM(CASE WHEN bit_col & 16 > 0 THEN 1 ELSE 0 END) "0010000"
, SUM(CASE WHEN bit_col & 8 > 0 THEN 1 ELSE 0 END) "0001000"
, SUM(CASE WHEN bit_col & 4 > 0 THEN 1 ELSE 0 END) "0000100"
, SUM(CASE WHEN bit_col & 2 > 0 THEN 1 ELSE 0 END) "0000010"
, SUM(CASE WHEN bit_col & 1 > 0 THEN 1 ELSE 0 END) "0000001"
FROM my_table
;
1000000 | 0100000 | 0010000 | 0001000 | 0000100 | 0000010 | 0000001
---------+---------+---------+---------+---------+---------+---------
11 | 8 | 11 | 13 | 11 | 9 | 8
To have the results in a single column you need to use union:
SELECT 1 AS "col", SUM(CASE WHEN bit_col & 64 > 0 THEN 1 ELSE 0 END) AS bit_count FROM my_table
UNION ALL SELECT 2 AS "col", SUM(CASE WHEN bit_col & 32 > 0 THEN 1 ELSE 0 END) AS bit_count FROM my_table
UNION ALL SELECT 3 AS "col", SUM(CASE WHEN bit_col & 16 > 0 THEN 1 ELSE 0 END) AS bit_count FROM my_table
UNION ALL SELECT 4 AS "col", SUM(CASE WHEN bit_col & 8 > 0 THEN 1 ELSE 0 END) AS bit_count FROM my_table
UNION ALL SELECT 5 AS "col", SUM(CASE WHEN bit_col & 4 > 0 THEN 1 ELSE 0 END) AS bit_count FROM my_table
UNION ALL SELECT 6 AS "col", SUM(CASE WHEN bit_col & 2 > 0 THEN 1 ELSE 0 END) AS bit_count FROM my_table
UNION ALL SELECT 7 AS "col", SUM(CASE WHEN bit_col & 1 > 0 THEN 1 ELSE 0 END) AS bit_count FROM my_table
ORDER BY bit_count DESC
;
position | bit_count
----------+-----------
6 | 6
7 | 6
4 | 4
5 | 4
2 | 0
3 | 0
1 | 0
http://docs.aws.amazon.com/redshift/latest/dg/r_OPERATOR_SYMBOLS.html
EDIT: If you would like something more dynamic you will need to look into using a UDF. You could start with my f_bitwise_to_string UDF as a template and add what you need from there. https://github.com/awslabs/amazon-redshift-udfs/blob/master/scalar-udfs/f_bitwise_to_string.sql
Let me explain what I've got and what I'm trying to achieve.
I have Table Look like this.
Let's say I have Table A: Booking
RoomNum ArrivalDate DepartureDate
101 2014-12-01 2014-12-03
102 2014-12-02 2014-12-03
103 2014-12-03 2014-12-04
101 2014-12-05 2014-12-06
the expected result should be something like the following :
RoomNum Des-01 Des-02 Des-03 Des-04 Des-05 Des-06
101 1 1 1 0 1 1
102 0 1 1 0 0 0
103 0 1 1 0 1 1
Any ideas would be very much appreciated.
Thanks in advance
One option you have, while it may not be efficient or dynamic, is to use the SUM() function. Inside of there, you can include a case statement.
In this case, I wrote a case statement that checks if the current date is between the arrival and departure dates of a room.
SELECT roomnum,
SUM(CASE WHEN '2014-12-01' BETWEEN arrivalDate AND departureDate THEN 1 ELSE 0 END) AS 'Dec-01',
SUM(CASE WHEN '2014-12-02' BETWEEN arrivalDate AND departureDate THEN 1 ELSE 0 END) AS 'Dec-02',
SUM(CASE WHEN '2014-12-03' BETWEEN arrivalDate AND departureDate THEN 1 ELSE 0 END) AS 'Dec-03',
SUM(CASE WHEN '2014-12-04' BETWEEN arrivalDate AND departureDate THEN 1 ELSE 0 END) AS 'Dec-04',
SUM(CASE WHEN '2014-12-05' BETWEEN arrivalDate AND departureDate THEN 1 ELSE 0 END) AS 'Dec-05',
SUM(CASE WHEN '2014-12-06' BETWEEN arrivalDate AND departureDate THEN 1 ELSE 0 END) AS 'Dec-06'
FROM booking
GROUP BY roomnum;
Here is an SQL Fiddle.
I am working on project where I have reports that have three states its "checked","inprocess" and "completed"
Got two tables!
tbl_tracking - for keeping track of reports
report_id usr_id date status
----------------------------------------------
0000 abc 2014/04/05 checked
0001 abc 2014/04/05 checked
0000 abc 2014/04/05 inprocess
0001 abc 2014/04/05 completed
0002 abc 2014/04/06 completed
0004 xyz 2014/04/05 checked
0005 xyz 2014/04/06 checked
tbl_timestatus- for keeping track of time employees have worked on reports
usr_id date time_worked (hrs)
----------------------------------------------
abc 2014/04/05 6
abc 2014/04/06 5
Now I want to create a view to always display up-to-date status of everything so I code this
CREATE VIEW VW_STATUS AS
SELECT tb1.usr_id, tb1.date,
COUNT(CASE tb1.status WHEN 'checked' THEN 1 ELSE NULL END) AS checkedcount,
COUNT(CASE tb1.status WHEN 'inprocess' THEN 1 ELSE NULL END) AS inprocesscount,
COUNT(CASE tb1.status WHEN 'completed' THEN 1 ELSE NULL END) AS compltedcount,
CASE WHEN (tb1.usr_id=tb2.usr_id AND tb1.date=tb2.date) THEN tb2.time_worked ELSE NULL END AS timeworked
FROM tbl_tracking tb1, tbl_timestatus tb2
GROUP BY tb1.usr_id, tb1.date;
Expected Output:
usr_id date checkedcount inprocesscount completedcount timeworked
---------------------------------------------------------------------------------------
abc 2014/04/05 2 1 1 6
abc 2014/04/06 0 0 1 5
xyz 2014/04/05 1 0 0 NULL
xyz 2014/04/06 1 0 0 NULL
Actual Output:
usr_id date checkedcount inprocesscount completedcount timeworked
---------------------------------------------------------------------------------------
abc 2014/04/05 4 2 2 6
abc 2014/04/06 0 0 2 5
xyz 2014/04/05 2 0 0 NULL
xyz 2014/04/06 2 0 0 NULL
While the "timeworked" values remain correct, the count(*)'s add themselves twice!! There is some problem with join! Need help on same..
You should try like below. See a sample fiddle here http://sqlfiddle.com/#!3/0b24c/6
CREATE VIEW VW_STATUS AS
SELECT tb1.usr_id, tb1.date,
COUNT(CASE tb1.status WHEN 'checked' THEN 1 ELSE NULL END) AS checkedcount,
COUNT(CASE tb1.status WHEN 'inprocess' THEN 1 ELSE NULL END) AS inprocesscount,
COUNT(CASE tb1.status WHEN 'completed' THEN 1 ELSE NULL END) AS compltedcount,
tb2.time_worked
FROM tbl_tracking tb1
LEFT JOIN tbl_timestatus tb2
ON tb1.usr_id=tb2.usr_id
AND tb1.date=tb2.date
GROUP BY tb1.usr_id, tb1.date , tb2.time_worked
ORDER BY tb1.usr_id;
Which results in
join tbl1 and tb2 on tb1.usr_id=tb2.usr_id AND tb1.date=tb2.date. Note that the time worked is correct.
I'm using MySQL. This is table i have
Level Programmingtime Clientname projectid
0 128 abc 3
1 32 abc 3
2 126 abc 3
3 541 abc 3
4 452 abc 3
1 32 abc 3
But now i have to show this data in crystal report in such a format like
projectid level0 level1 level2 level3 level4
3 128 32+32=(64) 126 541 452
(programmingtime)
Please tell me what will be the my syntax for such a difficult logic.
Thanks in advance.
Since the levels are known, you can simply do:
SELECT
projectid,
SUM(CASE WHEN level = 0 THEN programmingtime ELSE 0 END) AS level0,
SUM(CASE WHEN level = 1 THEN programmingtime ELSE 0 END) AS level1,
SUM(CASE WHEN level = 2 THEN programmingtime ELSE 0 END) AS level2,
SUM(CASE WHEN level = 3 THEN programmingtime ELSE 0 END) AS level3,
SUM(CASE WHEN level = 4 THEN programmingtime ELSE 0 END) AS level4
FROM
tbl
GROUP BY
projectid
I'm a bit confuse how to name my question title.
Let say my MySQL database table like this. table_group
UserID UserGroup UserStatus
------------------------------
1 1 1
2 1 1
3 1 2
4 2 3
5 3 2
6 3 1
7 4 3
9 4 4
10 4 1
I want to group it by UserGroup and count the UserStatus.
Let me know what is the correct statement to get the result like this
UserGroup Status_1 Status_2 Status_3 Status_4
-------------------------------------------------
1 2 2 0 0
2 0 0 1 0
3 1 1 0 0
4 1 0 1 1
SELECT UserGroup, count(UserStatus = 1) as Status_1, count(UserStatus = 2) as Status_2,
count(UserStatus = 3) as Status_3, count(UserStatus = 4) as Status_4
FROM table_group GROUP BY UserGroup
You could use case to count rows that match a condition:
select UserGroup
, count(case when UserStatus = 1 then 1 end) as Status_1
, count(case when UserStatus = 2 then 1 end) as Status_2
, count(case when UserStatus = 3 then 1 end) as Status_3
, count(case when UserStatus = 4 then 1 end) as Status_4
from table_group
group by
UserGroup