Using multiple group by having in single query - mysql

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

Related

how to subtract to sum(produced from same table) in MYSQL?

amount group
--------------
100 'a'
40 'b'
30 'a'
50 'b'
query output:
diff(a-b)
---------
40
how to do it in MYSQL?
You can simply:
SELECT (SELECT SUM(amount) FROM t WHERE `group` = 'a') -
(SELECT SUM(amount) FROM t WHERE `group` = 'b') AS diff
Or:
SELECT SUM(CASE
WHEN `group` = 'a' THEN amount
WHEN `group` = 'b' THEN -amount
END) AS diff
FROM t

MySql GROUP BY Max Date

I have a table called votes with 4 columns: id, name, choice, date.
****id****name****vote******date***
****1*****sam*******A******01-01-17
****2*****sam*******B******01-05-30
****3*****jon*******A******01-01-19
My ultimate goal is to count up all the votes, but I only want to count 1 vote per person, and specifically each person's most recent vote.
In the example above, the result should be 1 vote for A, and 1 vote for B.
Here is what I currently have:
select name,
sum(case when uniques.choice = A then 1 else 0 end) votesA,
sum(case when uniques.choice = B then 1 else 0 end) votesB
FROM (
SELECT id, name, choice, max(date)
FROM votes
GROUP BY name
) uniques;
However, this doesn't work because the subquery is indeed selecting the max date, but it's not including the correct choice that is associated with that max date.
Don't think "group by" to get the most recent vote. Think of join or some other option. Here is one way:
SELECT v.name,
SUM(v.choice = 'A') as votesA,
SUM(v.choice = 'B') as votesB
FROM votes v
WHERE v.date = (SELECT MAX(v2.date) FROM votes v2 WHERE v2.name = v.name)
GROUP BY v.name;
Here is a SQL Fiddle.
Your answer are close but need to JOIN self
Subquery get Max date by name then JOIN self.
select
sum(case when T.vote = 'A' then 1 else 0 end) votesA,
sum(case when T.vote = 'B' then 1 else 0 end) votesB
FROM (
SELECT name,Max(date) as date
FROM T
GROUP BY name
) AS T1 INNER JOIN T ON T1.date = T.date
SQLFiddle
Try this
SELECT
choice,
COUNT(1)
FROM
votes v
INNER JOIN
(
SELECT
id,
max(date)
FROM
votes
GROUP BY
name
) tmp ON
v.id = tmp.id
GROUP BY
choice;
Something like this (if you really need count only last vote of person)
SELECT
sum(case when vote='A' then cnt else 0 end) voteA,
sum(case when vote='B' then cnt else 0 end) voteB
FROM
(SELECT vote,count(distinct name) cnt
FROM (
SELECT name,vote,date,max(date) over (partition by name) maxd
FROM votes
)
WHERE date=maxd
GROUP BY vote
)
PS. MySQL v 8
select
name,
sum( case when choice = 'A' then 1 else 0 end) voteA,
sum( case when choice = 'B' then 1 else 0 end) voteB
from
(
select id, name, choice
from votes
where date = (select max(date) from votes t2
where t2.name = votes.name )
) t
group by name
Or output just one row for the total counts of VoteA and VoteB:
select
sum( case when choice = 'A' then 1 else 0 end) voteA,
sum( case when choice = 'B' then 1 else 0 end) voteB
from
(
select id, name, choice
from votes
where date = (select max(date) from votes t2
where t2.name = votes.name )
) t
Based on #d-shish solution, and since introduction (in MySQL 5.7) of ONLY_FULL_GROUP_BY, the GROUP BY statement must be placed in subquery like this :
SELECT v.`name`,
SUM(v.`choice` = 'A') as `votesA`,
SUM(v.`choice` = 'B') as `votesB`
FROM `votes` v
WHERE (
SELECT MAX(v2.`date`)
FROM `votes` v2
WHERE v2.`name` = v.`name`
GROUP BY v.`name` # << after
) = v.`date`
# GROUP BY v.`name` << before
Otherwise, it won't work anymore !

How to check if a certain value is existent or if it exists twice?

So i have a table that looks something like this:
ID CUR_Valid
1 N
1 N
1 N
1 N
1 N
1 Y
2 N
2 N
2 Y
3 Y
So as you can see one ID can only be allowed to have one y. I want to write a statment that shows me the IDs that have no Y or more then one Y.
My code so far looks like this:
Select [BILL_ID]
,[Bill_MONTH]
,[CUR_VALID]
,COUNT(CUR_VALID)
FROM DB.dbo.table
WHERE CUR_VALID = 'Y'
GROUP BY [BILL_ID]
,[Bill_MONTH]
,[CUR_VALID]
Having COUNT(CUR_VALID) > 1 OR COUNT(CUR_VALID) <1
I'm not sure whats wrong. Can someone point me into the right direction?
Try this answer. Hope this helps you:
Select [BILL_ID]
,[Bill_MONTH]
,[CUR_VALID]
,COUNT(CUR_VALID)
FROM DB.dbo.table
--WHERE CUR_VALID = 'Y'
GROUP BY [BILL_ID]
,[Bill_MONTH]
,[CUR_VALID]
Having COUNT(CASE WHEN CUR_VALID = 'Y' THEN 1 END) > 1 OR COUNT(CASE WHEN CUR_VALID = 'Y' THEN 1 END) <1
When you put WHERE CUR_VALID = 'Y' condition, it remove the records which don't have the the Y.
Try this update for, number of IDs.
Select COUNT(1)[No of Ids]
FROM DB.dbo.table
GROUP BY [BILL_ID]
,[Bill_MONTH]
,[CUR_VALID]
Having COUNT(CASE WHEN CUR_VALID = 'Y' THEN 1 END) > 1 OR COUNT(CASE WHEN CUR_VALID = 'Y' THEN 1 END) <1
It returns the Number of Ids.
use
SQL Aliases
Count as totalValid
Select [BILL_ID]
,[Bill_MONTH]
,[CUR_VALID]
,COUNT(CUR_VALID) as totalValid
FROM DB.dbo.table
WHERE CUR_VALID = 'Y'
GROUP BY [BILL_ID]
,[Bill_MONTH]
,[CUR_VALID]
Having totalValid > 1 OR totalValid <1
here is a sample query that demonstrates the identification of one with no Y or one with two or more Y's
with dat
as
(
select 1 id,'N' cur_valid union all
select 1,'N' union all
select 1,'N' union all
select 1,'N' union all
select 1,'N' union all
select 1,'Y' union all
select 2,'N' union all
select 2,'N' union all
select 2,'Y' union all
select 3,'Y' union all
select 4,'Y' union all /* two Ys */
select 4,'Y' union all
select 5,'N' /* no Y */)
select id
from
(
select id,sum(case when cur_valid='Y' then 1 else 0 end) x
from dat
group by id
) ilv
where x<>1
this can be condensed to
with dat
as
(
select 1 id,'N' cur_valid union all
select 1,'N' union all
select 1,'N' union all
select 1,'N' union all
select 1,'N' union all
select 1,'Y' union all
select 2,'N' union all
select 2,'N' union all
select 2,'Y' union all
select 3,'Y' union all
select 4,'Y' union all /* two Ys */
select 4,'Y' union all
select 5,'N' /* no Y */)
select id
from dat
group by id
having sum(case when cur_valid='Y' then 1 else 0 end)<>1
It is possible to use self join like this
select d1.id, count(d2.id)
from (select id from dat group by id) d1
left join dat d2 on d1.id = d2.id and d2.cur_valid = 'Y'
group by d1.id
having count(d2.id) <> 1
demo - thanks #Abbennett for the data

Multiple select with single Group By query

I have these 3 fields in the table.
trans_date | transaction_type | client_id
What I need is a count of entries by transaction_types for each date. For example,
Date : 07/07/2015 total count : 6 transaction_type 1 count : 3 ,
transaction_type 2 count : 1, transaction_type 3 count : 2 etc....
And I need this for all the dates grouped by each date.
Here's my current query,
SELECT count(id) as total_count,
(select count(id) where transaction_type=1) as type1_count,
(select count(id) where transaction_type=2) as type2_count,
(select count(id) where transaction_type=3) as type3_count
FROM tblTransactions
where client_id=1
GROUP BY date(trans_date/1000, 'unixepoch')
This returns weird numbers that doesn't match. What am I doing wrong?
The reason that you are getting weird values is that your sub queries are not filtered by date so you will get the total count for each transaction type. What you need is a correlated subquery that will get a paremeter from outer query:
SELECT count(id) as total_count,
(select count(id) where transaction_type=1 and trans_date=t.trans_date) as type1_count,
(select count(id) where transaction_type=2 and trans_date=t.trans_date) as type2_count,
(select count(id) where transaction_type=3 and trans_date=t.trans_date) as type3_count
FROM tblTransactions t
where client_id=1
GROUP BY date(trans_date/1000, 'unixepoch')
You can use sum function instead of subqueries
select date(trans_date/1000, 'unixepoch') d,
sum(case when transaction_type = 1 then 1 else 0 end) type1_count,
sum(case when transaction_type = 2 then 1 else 0 end) type2_count,
sum(case when transaction_type = 3 then 1 else 0 end) type3_count
from tblTransactions
where client_id=1
group by d

Transpose simple single column 3-row results into single row, 3-column one?

I have a statistical query that would return three rows (as I have 3 types by which I group by), I also know the order of the rows as I do explicit ORDER BY FIELD:
SELECT COUNT(id) AS c FROM Vehicles GROUP BY VehicleTypeID ORDER BY FIELD(VehicleTypeID, 1,2,3)
Is there a simple way to transpose the rows into columns? Something like (PSEUDO SQL):
SELECT c[0] AS CarsCount, c[1] AS MotorcyclesCount, c[2] AS TrucksCount FROM (
SELECT COUNT(id) AS c
FROM Vehicles
GROUP BY VehicleTypeID
ORDER BY FIELD(VehicleTypeID, 1,2,3)
)
Yes, it is a case statement with aggregation:
SELECT max(case when fieldnum = 1 then c end) AS CarsCount,
max(case when fieldnum = 2 then c end) AS MotorcyclesCount,
max(case when fieldnum = 3 then c end) AS TrucksCount
FROM (SELECT COUNT(id) AS c , FIELD(VehicleTypeID, 1,2,3) as fieldnum
FROM Vehicles
GROUP BY VehicleTypeID
) t;