How to select values by groups, using select sum()? - mysql

I need to select values by groups (from 0 to 10, from 10 to 50, more than 50).
user_id amount
1 20
1 40
2 5
3 30
3 1
Why this query doesn't work correctly?
select (select sum(amount)),
case
when (select sum(amount))<10 then '0-10'
when (select sum(amount))>=10 and (select sum(amount))<50 then '10-20'
else '>50' end as total_amount, count(distinct user_id)
from table
group by
case
when (select sum(amount))<10 then '0-10'
when (select sum(amount))>=10 and (select sum(amount))<50 then '10-20'
else '>50' end as total_amount, count(distinct user_id);
output
diapason number_of_users
0-10 1
10-50 1
>50 1
Give me hint plz

Your query has a number of issues, but primarily it will not work because you need to do the sum by user prior to the sorting into ranges. Try this instead:
SELECT CASE
WHEN amount BETWEEN 0 AND 9 THEN ' 0-10'
WHEN amount BETWEEN 10 AND 50 THEN '10-50'
ELSE '>50' END AS diapason,
COUNT(*) AS number_of_users
FROM (SELECT SUM(amount) AS amount
FROM payments
GROUP BY user_id) p
GROUP BY diapason;
Output
diapason number_of_users
0-10 1
10-50 1
>50 1

Try below way
select
sum(case when amount <10 then 1 else 0 end) as "0-10",
sum(case when amount >=10 and amount <50 then 1 else 0 end) as "0-50" , sum(case when amount>50 then 1 else 0 end) as ">50"
from table

Your syntax is incorrect:
select case
when amount<10 then '0-10'
when samount>=10 and amount<50 then '10-20'
else '>50' end as total_amount, count(distinct user_id)
from table
group by
case
when amount<10 then '0-10'
when samount>=10 and amount<50 then '10-20'
else '>50' end

You can try this, writting a subquery get SUM of amount by each user_id, then do CASE WHEN, you don't need select sum(amount) in CASE WHEN.
CREATE TABLE t(
user_id int,
amount int
);
insert into t values(1,20);
insert into t values(1,40);
insert into t values(2,5);
insert into t values(3,30);
insert into t values(3,1);
Query 1:
select
case
when t1.total<10 then '0-10'
when t1.total>=10 and t1.total<50 then '10-50'
else '>50' end as diapason,
count(distinct user_id) number_of_users
from (
SELECT user_id,SUM(amount) total
FROM table
GROUP BY user_id
) t1
group by
case
when t1.total<10 then '0-10'
when t1.total>=10 and t1.total<50 then '10-50'
else '>50' end
Results:
| diapason | number_of_users |
|----------|-----------------|
| 0-10 | 1 |
| 10-50 | 1 |
| >50 | 1 |

Related

The minimum value from each category

I want to get out the minimum price for categories 1, 2 and 3
I've used
LEAST(MIN(price_reduced),MIN(price))
IFNULL(MIN(price_reduced),MIN(price)) ... WHERE price <> 0 and price_reduced <> 0
Database
id
category
price
price_reduced
1
1
200
100
2
1
300
0
3
1
500
0
4
2
200
150
5
2
125
0
6
3
300
0
7
3
200
90
Output
1 - 100
2 - 125
3 - 90
Thank you
This query will work on all MySQL V4+ :
SELECT Category,
MIN(IF((price_reduced > 0) AND (price_reduced < price), price_reduced, price)) AS P
FROM your_table GROUP BY Category;
Maybe with cte:
WITH cte AS (SELECT category,
MIN(price) AS mp,
MIN(CASE WHEN price_reduced <= 0 THEN 9999 ELSE price_reduced END) pr
FROM mytable
GROUP BY category)
SELECT category, LEAST(mp, pr) AS min_val
FROM cte;
Or without cte but with derived table:
SELECT category, LEAST(mp, pr) AS min_val
FROM (SELECT category,
MIN(price) AS mp,
MIN(CASE WHEN price_reduced <= 0 THEN 9999 ELSE price_reduced END) pr
FROM mytable
GROUP BY category) a;
Or just a single query:
SELECT category,
LEAST(MIN(price),
MIN(CASE WHEN price_reduced <= 0 THEN 9999 ELSE price_reduced END)) AS min_val
FROM mytable
GROUP BY category;
All return the same results.
Demo fiddle

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

Sql query for clubbing the data according to date

I have a table like this. Now I want to show the total of same dates of different status in single row.
What should be the query?
Expected Result
Created | Total1 | Total2 | Total3
2017-02-28 | 1 | 1 | 2
you could use a sum for case when for each status and group by
select
created
, sum( case when story_status ='Draft' then total else 0 end ) as Draft_count
, sum( case when story_status ='Private' then total else 0 end ) as Private_count
, sum( case when story_status ='Published' then total else 0 end ) as Published_count
from my_table
group by created
This will give you one row per date created, with columns for each story_status:
SELECT
`created`,
SUM(if(`story_status` = 'Draft',`total`,0)) as `Total Draft`,
SUM(if(`story_status` = 'Private',`total`,0)) as `Total Private`,
SUM(if(`story_status` = 'Published',`total`,0)) as `Total Published`
FROM table
GROUP BY `created`
ORDER BY `created`

how to marge the values of column in mysql

Lets consider this query
select class_id,case when event_id=2 then sum(time_spent) end as timespent ,case when event_id=3 then sum(timespent) end as visitedtimespent from class group by class_id,event_id;
output is looking like
class_id timespent visitedtimespent
1 2000 NULL
1 NULL 10
2 4000 NULL
2 NULL 5
when I use this query
select class_id,case when event_id=2 then sum(time_spent) end as timespent ,case when event_id=3 then sum(time_spent) end as timespent from class group by class_id;
output is looking like
class_id timespent visitedtimespent
1 2000 NULL
2 4000 NULL
but I expected this output
class_id timespent visitedtimespent
1 2000 10
2 4000 5
how can I achieve this?
select class_id,
sum(case when event_id=2 then time_spent else 0 end) as timespent,
sum(case when event_id=3 then time_spent else 0 end) as visitedtimespent
from class
group by class_id
sum the case.
select class_id,
sum(case when event_id=2 then time_spent end) as timespent ,
sum(case when event_id=3 then time_spent end) as visitedtimespent
from class group by class_id;
to explain the difference:
case when id... then sum(value) is equivalent to
select case when id then value from
(
select id, sum(value) as value from table
)subquery
which is an illegal grouping(ID is not aggregated or included in grouping, so the ID value will be chosen at random between all existing entries), and your ID information will be lost. IF you then apply a case to the ID info, you will not get relevant results.

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