I have the table structure below
I want to be able to select the following groups
farmers who grow between 1 and 3 commodities
farmers who grow between 4 and 6 commodities
farmers who grow more than 6 commodities
My resultant query should look like below
I am completely lost as to how to go about this query. I tried
SELECT count(*) AS total,
(SELECT count(farmer_id) from farmer_commodities HAVING count(commodity_id) < 3) AS grow1_3,
(SELECT count(farmer_id) from farmer_commodities HAVING count(commodity_id) BETWEEN 4 AND 6) AS grow4_6,
(SELECT count(farmer_id) from farmer_commodities HAVING count(commodity_id) > 6) as grow_above_6
from farmer_commodities
Try this
With data as (
SELECT farmer_id,
count(commodity_id) cnt
From table group by
farmer_id)
Select
count(*),
Count(distinct case when cnt
< 3 then farmer_id end),
Count(distinct case when cnt
BETWEEN 4 AND 6 then farmer_id end),
Count(distinct case when cnt> 6 then farmer_id end) from
Data;
Can you do this:
select grow1_3_commodities, grow4_6_commodities, grow_above_6_commodities from (
(select farmer_id, count(commodity_id) as grow1_3_commodities from farmer_commodities group by farmer_id HAVING count(commodity_id) < 3) AS grow1_3
join (select farmer_id, count(commodity_id) as grow4_6_commodities from farmer_commodities group by farmer_id HAVING count(commodity_id) BETWEEN 4 AND 6) AS grow4_6
join (SELECT farmer_id, count(farmer_id) as grow_above_6_commodities from farmer_commodities group by farmer_id HAVING count(commodity_id) > 6) as grow_above_6)
where grow1_3.farmer_id = grow4_6.farmer_id and grow4_6.farmer_id = grow_above_6.farmer_id);
Related
I have 2 tables Users and Posts and I need only number of users who have more than 3 posts and who have more than 5 posts.
I need something like this:
NumberOfUsers
Posts
555
>3
888
>5
SELECT
COUNT( u.Id)
FROM
Users u
INNER JOIN Posts p ON (u.Id=p.OwnerId)
HAVING COUNT(p.Id)>3
I try this but having count does not work I think.
You can use two levels of aggregation
select sum(case when cnt > 3 then 1 else 0 end) cnt_3,
sum(case when cnt > 5 then 1 else 0 end) cnt_5
from (select ownerid, count(*) cnt from posts group by ownerid) p
Note that you don't need to bring in the users table ; the posts table has all the information we need.
Depending on your database, syntax shortcuts might be available, as in MySQL :
select sum(cnt > 3) cnt_3,
sum(cnt > 5) cnt_5
from (select ownerid, count(*) cnt from posts group by ownerid) p
Or in Posgres :
select count(*) where(cnt > 3) cnt_3,
count(*) where(cnt > 5) cnt_5
from (select ownerid, count(*) cnt from posts group by ownerid) p
This question already has answers here:
Add a summary row with totals
(6 answers)
Closed 4 years ago.
SELECT COUNT(*) AS customer, t.state
FROM tbl_parcel_item t
WHERE t.courier_name='Tnt'
AND t.date = '2018-03-12'
AND t.ship_status NOT IN (0,1,9,10)
GROUP BY t.state`
Based on the sql above the results would be:
enter image description here
How to make it get total of the result above for example :
enter image description here
Use with rollup:
SELECT COUNT(*) AS customer, t.state`
FROM tbl_parcel_item t
WHERE t.courier_name = 'Tnt' AND
t.date = '2018-03-12' AND
t.ship_status NOT IN (0, 1, 9, 10)
GROUP BY t.state WITH ROLLUP;
Use union all:
`SELECT COUNT(*) AS customer, t.state`
`FROM tbl_parcel_item t`
`WHERE t.courier_name='Tnt'`
`AND t.date = '2018-03-12'`
`AND t.ship_status NOT IN (0,1,9,10)`
`GROUP BY t.state`
`UNION ALL`
`SELECT COUNT(*) AS customer, 'Total' as state`
`FROM tbl_parcel_item t`
`WHERE t.courier_name='Tnt'`
`AND t.date = '2018-03-12'`
`AND t.ship_status NOT IN (0,1,9,10)`
Use ROLLUP:
SELECT
COALESCE(t.state, 'TOTAL') AS state,
COUNT(*) AS customer
FROM tbl_parcel_item t
WHERE
t.courier_name = 'Tnt' AND
t.date = '2018-03-12' AND
t.ship_status NOT IN (0,1,9,10)
GROUP BY t.state WITH ROLLUP;
01) WITH ROLLUP as Explained in the other answers
02)
Use Union Query
SELECT t.state, COUNT(*) AS customer FROM tbl_parcel_item t WHERE t.courier_name='Tnt' AND t.date = '2018-03-12' AND t.ship_status NOT IN (0,1,9,10) GROUP BY t.state
UNION
SELECT 'Total', COUNT(*) AS customer FROM tbl_parcel_item t WHERE t.courier_name='Tnt' AND t.date = '2018-03-12' AND t.ship_status NOT IN (0,1,9,10)
I need to find the cumulative sum for the following data:
Following query:
SELECT created, COUNT( * )
FROM `transactions`
GROUP BY created
Gives me:
created COUNT( * )
2015-8-09 1
2015-8-15 1
2015-8-16 2
2015-8-17 1
2015-8-23 1
I tried to do the cumulative sum like:
SELECT t1.created, COUNT( * ) , SUM( t2.totalcount ) AS sum
FROM transactions t1
INNER JOIN (
SELECT id, created c, COUNT( * ) AS totalcount
FROM transactions
GROUP BY created
ORDER BY created
)t2 ON t1.id >= t2.id
GROUP BY t1.created
ORDER BY t1.created
but the results it gives arent as expected:
created COUNT( * ) sum
2015-8-09 5 6
2015-8-15 3 4
2015-8-16 6 8
2015-8-17 1 1
2015-8-23 4 5
How do i produce the following result:
created COUNT( * ) sum
2015-8-09 1 1
2015-8-15 1 2
2015-8-16 2 4
2015-8-17 1 5
2015-8-23 1 6
select tmp.*, #sum := #sum + cnt as cum_sum
from
(
SELECT created, COUNT( * ) as cnt
FROM `transactions`
GROUP BY created
ORDER BY created
) tmp
cross join (select #sum := 0) s
Your inner query is selecting id without grouping on it. Let's rework it in terms of the date.
SELECT t1.created, COUNT( * ) AS daycount, SUM( t2.totalcount ) AS sum
FROM transactions t1
INNER JOIN ( SELECT created, COUNT( * ) AS totalcount
FROM transactions
GROUP BY created
) t2 ON t1.created >= t2.created
GROUP BY t1.created
ORDER BY t1.created;
Or you might want to put the totalcount inline:
SELECT t1.created, COUNT(*) AS daycount
, ( SELECT COUNT(*) FROM transactions t2
WHERE t2.created <= t1.created ) AS totalcount
FROM transactions t1
GROUP BY created
ORDER BY CREATED;
Having some trouble figuring out the best way to do this.
Here is what I'm trying to do:
SELECT
YEAR(t.voucher_date) as period,
COUNT(t.id) as total_count,
(SELECT COUNT(t2.id) FROM booking_global as t2 where t2.booking_status = 'CONFIRMED') as confirmed,
(SELECT COUNT(t3.id) FROM booking_global as t3 where t3.booking_status = 'PENDING') as pending
FROM booking_global t
GROUP BY YEAR(t.voucher_date)
This produces the below result.
period total_count CONFIRMED PENDING
2014 4 5 3
2015 4 5 3
Expected Result
period total_count CONFIRMED PENDING
2014 4 3 1
2015 4 2 2
Here i want to get CONFIRMED / PENDING count's for respective years, rather than getting count of all statuses.
I am not sure how to use my query as a sub query and run another query on the results.
Flowing should give you right rsult
SELECT
YEAR(t.voucher_date) as period,
COUNT(t.id) as total_count,
(SELECT COUNT(t2.id) FROM booking_global as t2 where t2.booking_status = 'CONFIRMED' and YEAR(t2.voucher_date) = YEAR(t.voucher_date)) as confirmed,
(SELECT COUNT(t3.id) FROM booking_global as t3 where t3.booking_status = 'PENDING' and YEAR(t3.voucher_date) = YEAR(t.voucher_date)) as pending
FROM booking_global t
GROUP BY YEAR(t.voucher_date)
You can have a subquery that calculates each booking_status for each year. The result of which is then joined on table booking_global. Example,
SELECT YEAR(t.voucher_date) voucher_date_year,
COUNT(t.id) total_count,
IFNULL(calc.confirmed_count, 0) confirmed_count,
IFNULL(calc.pending_count, 0) pending_count
FROM booking_global t
LEFT JOIN
(
SELECT YEAR(voucher_date) voucher_date_year,
SUM(booking_status = 'CONFIRMED') confirmed_count,
SUM(booking_status = 'PENDING') pending_count
FROM booking_global
GROUP BY YEAR(voucher_date)
) calc ON calc.voucher_date_year = YEAR(t.voucher_date)
GROUP BY YEAR(t.voucher_date)
I have 2 queries to get the count of families having count = 1 and count = 2.
SELECT Name, count(*) as c FROM Tablename GROUP BY HOUSE_NO HAVING c<=1;
SELECT Name, count(*) as c FROM Tablename GROUP BY HOUSE_NO HAVING c>=2 and c<=4;
But i need to combine those queries into single query.Like
count1 count2
nooffamiliesHavingcount = 1 nooffamiliesHavingcount = 2
Please help me....Thanks in advance..
You need to put your first count into a subquery:
SELECT COUNT(CASE WHEN C = 1 THEN 1 END) AS nooffamiliesHavingcount1,
COUNT(CASE WHEN C = 2 THEN 1 END) AS nooffamiliesHavingcount2
FROM ( SELECT COUNT(*) AS C
FROM TableName
GROUP BY House_No
) t
WHERE c IN (1, 2);
EDIT
If you need to do ranges in your count you can use this:
SELECT COUNT(CASE WHEN C <= 1 THEN 1 END) AS nooffamiliesHavingcount1,
COUNT(CASE WHEN C BETWEEN 2 AND 4 THEN 1 END) AS nooffamiliesHavingcount2,
COUNT(CASE WHEN C > 4 THEN 1 END) AS nooffamiliesHavingcount3
FROM ( SELECT COUNT(*) AS C
FROM TableName
GROUP BY House_No
) t
Example on SQL Fiddle
SELECT CASE WHEN c <= 1 THEN "<=1"
WHEN c BETWEEN 2 and 4 THEN "2-4"
END familysize,
COUNT(*) nooffamilies
FROM (SELECT Name, count(*) c
FROM Tablename
GROUP BY Name) x
GROUP BY familysize
HAVING familysize IS NOT NULL
FIDDLE