multiple selects on one table - mysql

I have a table called list and i have to extract the following.
fields are id and date
If date<20120401 then count on id >>>> give result
If date>20120401 then count on id >>>> give result
if there are 20 items of date<20120401 and 30 items of date>20120401 of an idnumber xyz
then the result should be...
xyz 20 30
I have done like ...
select
(select count(id) from list where id='xyz' and date<20120401) as date1,
(select count(id) from list where id='xyz' and date>20120401) as date2;
the result is 20 30
but how to print the idnumber?

SELECT
id,
SUM(CASE WHEN date < 20120401 THEN 1 ELSE 0 END) AS date1,
SUM(CASE WHEN date > 20120401 THEN 1 ELSE 0 END) AS date2,
FROM list
WHERE id = 'xyz'
GROUP BY id
UPDATE:
SELECT
list.id,
idmaster.idlocation,
SUM(CASE WHEN list.date < 20120401 THEN 1 ELSE 0 END) AS date1,
SUM(CASE WHEN list.date > 20120401 THEN 1 ELSE 0 END) AS date2,
FROM list
INNER JOIN idmaster ON list.id = idmaster.idnumber
WHERE list.id = 'xyz'
GROUP BY id

Try
select id, count(id) from list where id='xyz' and date < 20120401
union
select id, count(id) from list where id='xyz' and date > 20120401

You are looking for GROUP BY clause and maybe something like this:
SELECT
l2.id,
(SELECT COUNT(id)
FROM list l1
WHERE l1.id = l2.id AND date < 20120401) AS date1,
(SELECT COUNT(id)
FROM list l1
WHERE l1.id = l2.id AND date > 20120401) AS date2
FROM
list l2
GROUP BY
l2.id
There are more cost effective methods to get desired result, but this is the easiest to understand.

Try this:
SELECT
id,
SUM(CASE WHEN date < 20120401
THEN 1 ELSE 0 END) AS date1,
SUM(CASE WHEN date > 20120401
THEN 1 ELSE 0 END) AS date2,
FROM list
WHERE id = 'xyz'
GROUP BY id

Related

Count different values in a column, while doing total and group by different column values

We have a table with data from different nodes and one of the column will have status report as "compliant or non-compliant", sample data as below
I want to filter the table in such a way that if any of the checks on a node shows non compliant, it should be flagged as non-compliant and rest as compliant. Using below query i am able to do it
SELECT COUNT(*) AS total_nodes,
SUM(fully_compliant = 0) AS Non_compliant_nodes,
SUM(fully_compliant = 1) AS compliant_nodes
FROM (
SELECT Node, CASE WHEN SUM(Status = 'Compliant') = COUNT(*) THEN 1 ELSE 0 END AS fully_compliant
FROM your_table GROUP BY Node
)
Now, i want to group and split the result by dept as below, how can i achieve this
I think you're looking for this:
select dept,
count(*) as total_nodes,
sum(case when non_compliant_chk = 0 then 1 else 0 end) as compliant_nodes,
sum(case when non_compliant_chk > 0 then 1 else 0 end) as non_compliant_nodes
from (
select dept,
node,
sum(case when 'Non-Compliant' then 1 else 0 end) as non_compliant_chk
from your_table
group by dept,
node
) v
group by dept;
With few modifications to what Brian suggested, I am able to get the desired result
select dept,
count(*) as total_nodes,
sum(case when non_compliant_chk = 0 then 1 else 0 end) as compliant_nodes,
sum(case when non_compliant_chk > 0 then 1 else 0 end) as non_compliant_nodes
from (
select dept,
node,
COUNT(CASE WHEN Compliance-Status = 'Non-Compliant' THEN 1 END) 'non_compliant_chk'
from table WHERE DOR >= DATE(NOW()) - INTERVAL 7 DAY
group by Dept,
Node
) v
group by Dept;

how to get column count

i have a query like below
select project_task_id,
status_id,
sum(case when StatusID=1 then 1 else 0 end) as task_id=1,
sum(case whenStatusID=2 then 1 else 0 end) as task_id=2,
sum(case when StatusID=3 then 1 else 0 end) as task_id=3,
sum(case when StatusID=4 then 1 else 0 end) as task_id=4,
sum(case when StatusID=5 then 1 else 0 end) as task_id=5,
sum(case when StatusID=6 then 1 else 0 end) as task_id=6,
sum(case when StatusID=7 then 1 else 0 end) as task_id=7,
from"Projects".work_unit_status
group by project_task_id,status_id;
I'm getting the below attached output:
https://i.stack.imgur.com/1wfD1.png
and I want to get the below expected output:
https://i.stack.imgur.com/Zql9z.png
include zero's if the status_id is blank
please any one help on this
Try this: use the addition of all sum column
select project_task_id,status_id,
isnull(sum(case when StatusID=1 then 1 else 0 end),0)+
isnull(sum(case whenStatusID=2 then 1 else 0 end),0) +
isnullsum(case when StatusID=3 then 1 else 0 end),0) +
isnullsum(case when StatusID=4 then 1 else 0 end),0)+
isnullsum(case when StatusID=5 then 1 else 0 end),0) +
isnullsum(case when StatusID=6 then 1 else 0 end),0) +
isnullsum(case when StatusID=7 then 1 else 0 end),0) as count_status
from"Projects".work_unit_status group by project_task_id,status_id
use in with your case
with t1 as (
select project_task_id,
status_id,
sum(case when StatusID in (1,2,3,4,5,6,7) then 1 else 0)
as sum_s
from "Projects".work_unit_status
group by project_task_id,status_id
) ,
t2 as
(
select * from (
select 1 as statusid
union
select 2
union
select 3
union
select 4
union
select 5
union
select 6
union
select 7 ) t
) select t1.project_task_id,
t2.statusid,
case when t1.sum_s>0 or not null
then sum_s else 0 end as total
t2 full join t1 on t2.statusid=t1.status_id
Without knowing the exact table structure I assumed that status_id and statusId refer to the same column. (If they are different columns, we need to use StatusId in the COUNT.)
Based on the expected output, you want to count the status_id and group by project_task_id. To make sure that every status is represented for every task, first, we need to create a subquery of all possible project_task_id/status_id combinations. Then we use that with the aggregate values of the original table.
select
ps.project_task_id,
ps.status_id,
count(w.status_id) as total
from (
select distinct
project_task_id,
s.status_id
from work_unit_status
cross join (select distinct status_id from work_unit_status) s
) ps
left join work_unit_status w
on ps.project_task_id = w.project_task_id and ps.status_id = w.status_id
group by
ps.project_task_id,
ps.status_id
If you really need to hardcode the statuses from 1 to 7, use the query below.
select
ps.project_task_id,
ps.status_id,
count(w.status_id) as total
from (
select distinct
project_task_id,
s.status_id
from work_unit_status
cross join (
select 1 as status_id
union select 2
union select 3
union select 4
union select 5
union select 6
union select 7
) s
) ps
left join work_unit_status w
on ps.project_task_id = w.project_task_id and ps.status_id = w.status_id
group by
ps.project_task_id,
ps.status_id
order by
ps.project_task_id,
ps.status_id

How to select count(distinct) with additional where clause in MySQL?

I have a query that looks like this:
SELECT clicks.offer_id, count(distinct clicks.transaction_id) as unique_clicks
FROM clicks
WHERE date > '2014-12-01 17:43:30' and offer_id = 1;
This query counts the number of unique clicks by their transaction ID for an offer.
Now, I want to add the unique number of clicks for mobile and desktop users. Along the lines of:
SELECT clicks.offer_id, count(distinct clicks.transaction) as unique_clicks,
sum(case when clicks.mobile = 1 then 1 else 0 end) as mobile_unique_clicks,
sum(case when clicks.mobile = 0 then 1 else 0 end) as desktop_unique_clicks
FROM clicks
WHERE date > '2014-12-01 17:43:30' and offer_id = 1;
The problem with this is that it won't count unique transaction IDs. Is there a way to do this with one query? And what kind of covering indexes would I need to keep this efficient?
SELECT clicks.offer_id, count(distinct clicks.transaction_id) as unique_clicks,
count(DISTINCT case when clicks.mobile = 1 then clicks.transaction_id else null end) as mobile_unique_clicks,
count(DISTINCT case when clicks.mobile = 0 then clicks.transaction_id else null end) as desktop_unique_clicks
FROM clicks
WHERE date > '2014-12-01 17:43:30' and offer_id = 1;
You can use COUNT(DISTINCT ...)
something like this?
SELECT clicks.offer_id,
count(distinct clicks.transaction_id) as unique_clicks,
sub.mobile_unique_clicks,
count(distinct clicks.transaction_id) - sub.mobile_unique_clicks as desktop_unique_clicks
FROM clicks
JOIN
(
SELECT clicks.offer_id, count(distinct clicks.transaction_id) as mobile_unique_clicks,
FROM clicks
WHERE date > '2014-12-01 17:43:30' and offer_id = 1 AND clicks.mobile = 1
) sub
WHERE date > '2014-12-01 17:43:30' and offer_id = 1;
If I'm understanding your question correctly, you can move your query to a subquery and use distinct:
select offer_id,
count(transaction) unique_clicks,
count(case when mobile = 1 then 1 end) mobile_unique_clicks,
count(case when mobile = 0 then 1 end) desktop_unique_clicks
from (
select distinct offer_id, transaction, mobile
from clicks
where date > '2014-12-01 17:43:30' and offer_id = 1
) t
group by offer_id

SQL QUERY- multiple COUNT returns wrong (same) results when using in GROUP BY

I will simplfy this:
I have two SQL expressions which works OK:
First:
select count(*) as number1
from T1
where DATE1>'2012-01-01' and DATE2<'2012-12-31'
Result:13
select count(*) as number2
from T1
where DATE3>DATE2 and CURDATE()>DATE2
Result:5
But when I try to insert those two COUNTS in GROUP BY I am getting as resulyt always 13!!!
SELECT NAME,
COUNT(case when DATE1>'2012-01-01' and DATE2<'2012-12-31' then 1 else 0 end) as number1,
COUNT (case when (DATE3>DATE2 and CURDATE()>DATE2) then 1 else 0 end) as number 2
from T1
I am getting as result:
NAME NUMBER1 NUMBER2
A 5 5
B 4 4
C 4 4
But I should get:
NAME NUMBER1 NUMBER2
A 5 4
B 4 0
C 4 1
So that SUM of columns be 13 and 5 like in first two queries . What am I doing wrong?
Thank you
COUNT(expression) counts not null expressions. You can modify your query by changing the ELSE 0 to ELSE NULL or by removing it (the ELSE NULL is implied at CASE expressions):
SELECT name,
COUNT(CASE WHEN date1 > '2012-01-01' AND date2 < '2012-12-31'
THEN 1 END
) AS number1,
COUNT(CASE WHEN date3 > date2 AND CURDATE() > date2
THEN 1 END
) AS number2
FROM T1
GROUP BY name ;
Do not use count here.Use Sum. If you want to use the count then put null in else instead of 0
try:
SELECT NAME,
(select count(*) from T1 where DATE1>'2012-01-01' and DATE2<'2012-12-31') AS number1,
(select count(*) from T1 where DATE3>DATE2 and CURDATE()>DATE2) AS number2
FROM T1
GROUP BY NAME
Try this:
SELECT name,
SUM(CASE WHEN DATE1>'2012-01-01' AND DATE2<'2012-12-31' THEN 1 ELSE 0 END) AS number1,
SUM(CASE WHEN (DATE3>DATE2 AND CURDATE()>DATE2) THEN 1 ELSE 0 END) AS number2
FROM T1 GROUP BY name

MySQL CASE Statement with multiple columns in statement list

I have this query, which I know doesn't work, but I've left it as it is as pseudo-code to help explain what I'm doing. I'm trying to get "Booking" and "Sales" totals from a Booking table by day-of-the-week for the past week. Hence, Mon1B = Bookings for Monday and Mon1S = Sales for Monday.
SELECT
CASE WEEKDAY(b.created)
WHEN 0 THEN (SELECT COUNT(uuid) as Mon1B, SUM(amount) as Mon1S)
WHEN 1 THEN (SELECT COUNT(uuid) as Tue1B, SUM(amount) as Tue1S)
WHEN 2 THEN (SELECT COUNT(uuid) as Wed1B, SUM(amount) as Wed1S)
WHEN 3 THEN (SELECT COUNT(uuid) as Thu1B, SUM(amount) as Thu1S)
WHEN 4 THEN (SELECT COUNT(uuid) as Wed1B, SUM(amount) as Wed1S)
WHEN 5 THEN (SELECT COUNT(uuid) as Wed1B, SUM(amount) as Wed1S)
WHEN 6 THEN (SELECT COUNT(uuid) as Wed1B, SUM(amount) as Wed1S)
END CASE
FROM Bookings b
WHERE b.created > '#week1Start#' and b.created <= '#week1End#'
How can something like this be done in MySQL?
Yes, but case can only return one value. You can do it like this:
SELECT sum(CASE when WEEKDAY(b.created) = 0 then 1 else 0 end) as Mon1b,
sum(case when weekday(b.created) = 0 then amount else 0 end) as Mon1S,
...
FROM Bookings b
WHERE b.created > '#week1Start#' and b.created <= '#week1End#'
You might find it easier as 7 rows, though:
select WEEKDAY(b.created), count(*) as cnt, sum(amount) as amt
from Bookings b
WHERE b.created > '#week1Start#' and b.created <= '#week1End#'
group by WEEKDAY(b.created)
order by 1
I think you want something like this:
SELECT COUNT(IF(WEEKDAY(b.created)=0,uuid,NULL)) AS Mon1B
, SUM(IF(WEEKDAY(b.created)=0,amount,NULL)) AS Mon1S
, COUNT(IF(WEEKDAY(b.created)=1,uuid,NULL)) AS Tue1B
, SUM(IF(WEEKDAY(b.created)=1,amount,NULL)) AS Tue1S
Or, if you prefer the equivalent (but lengthier) CASE expression:
SELECT COUNT(CASE WEEKDAY(b.created) WHEN 0 THEN uuid END) AS Mon1B
, SUM(CASE WEEKDAY(b.created) WHEN 0 THEN amount END) AS Mon1S
, COUNT(CASE WEEKDAY(b.created) WHEN 1 THEN uuid END) AS Tue1B
, SUM(CASE WEEKDAY(b.created) WHEN 1 THEN amount END) AS Tue1S
The result of a CASE expression is a scalar; it can't return more than one value.
SELECT WEEKDAY(b.created),
CASE
WHEN b.weekday='Monday' THEN (SELECT COUNT(b.uuid) as Mon1B, SUM(s.amount) as Mon1S from bookings b,sales s where b.day='Monday' and s.day='Monday')
WHEN b.weekday='Tuesday' THEN (SELECT COUNT(b.uuid) as Tue1B, SUM(s.amount) as Tue1 from bookings b,sales s where b.day='Tuesday' and s.day='tuesday')
WHEN b.weekday='Wednesday' THEN (SELECT COUNT(b.uuid) as Wed1B, SUM(s.amount) as Wed1S from bookings b,sales s where b.day='wednesday' and s.day='wednesday')
WHEN b.weekday='Thursday' THEN (SELECT COUNT(b.uuid) as Thu1B, SUM(s.amount) as Thu1S from bookings b,sales s where b.day='Thursday' and s.day='Thursday')
WHEN b.weekday='Friday' THEN (SELECT COUNT(b.uuid) as Fri1B, SUM(s.amount) as Fri1S from bookings b,sales s where b.day='Friday' and s.day='Friday')
WHEN b.weekday='saturaday' THEN (SELECT COUNT(b.uuid) as Sat1B, SUM(s.amount) as sat1S from bookings b,sales s where b.day='Saturaday' and s.day='Saturaday')
WHEN b.weekday='Sunday' THEN (SELECT COUNT(b.uuid) as sun1B, SUM(s.amount) as sun1S from bookings b,sales s where b.day='Sunday' and s.day='Sunday')
END CASE
FROM Bookings b
WHERE b.created > '#week1Start#' and b.created <= '#week1End#'