Suppose I have a table with columns ID and Content populated with data.
ID | Content
1 | a
1 | b
1 | c
2 | b
2 | a
3 | b
I want to find every ID that has at least one of each 'a', 'b', and 'c' so the returned table would be :
ID | Content
1 | a
1 | b
1 | c
Using conditional SUM validate if inside the group id exist 1 or more of each element.
Then select DISTINCT ID, Content to eliminate possible duplicates
SELECT DISTINCT ID, Content
From YourTable
WHERE ID IN (SELECT ID
FROM YourTable
GROUP BY ID
HAVING SUM(case when Content = 'a' then 1 else 0 end) >= 1
AND SUM(case when Content = 'b' then 1 else 0 end) >= 1
AND SUM(case when Content = 'c' then 1 else 0 end) >= 1
)
select * from (
where
Select ID ,SUM(case when Content = 'a' then 1 else 0 end) as sum_a ,UM(case when Content = 'b' then 1 else 0 end) as sum_b,
SUM(case when Content = 'c' then 1 else 0 end) as sum_c
FROM table
Group by ID)x
where x.sum_a >1 or sum_b>1 or sum_c>1
Here is another approach that checks for a certain number of distinct "content" items per ID. Here is a link to an SQL Fiddle for this solution.
select
id,
count(distinct(content))
from tableX
group by id
having count(distinct(content)) = 3;
Related
This question already has answers here:
multiple query same table but in different columns mysql
(4 answers)
Closed 4 years ago.
Here is my table:
| ID | TYPE |
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 0 |
| 5 | 0 |
and now, I want to count how many records exists with TYPE=1 and how many records exist with TYPE = 0. Is it possible?
I know, I can do it in two queries:
SELECT COUNT(*) AS all_zero FROM `table WHERE type = 0;
SELECT COUNT(*) AS all_one FROM `table WHERE type = 1;
but I want do it in one query.
Is it possible?
Conditional aggregation will do it...
SELECT SUM(t.type=0) AS cnt_zero
, SUM(t.type=1) AS cnt_one
, SUM(t.type IN (0,1)) AS cnt_one_and_zero
, SUM(1) AS cnt_all
FROM mytable t
;
Note that the usage of type=0 and type=1 is MySQL-specific shorthand, which other database probably wouldn't accept.
If we ignore the handling of NULL values, this is basically equivalent to
SELECT SUM(IF( t.type=0 ,1,0)) AS cnt_zero
, SUM(IF( t.type=1 ,1,0)) AS cnt_one
, SUM(IF( t.type IN (0,1), 1,0)) AS cnt_one_and_zero
, SUM(1) AS cnt_all
FROM mytable t
;
A more ANSI standard compliant equivalent
SELECT SUM(CASE WHEN t.type=0 THEN 1 ELSE 0 END) AS cnt_zero
, SUM(CASE WHEN t.type=1 THEN 1 ELSE 0 END) AS cnt_one
, SUM(CASE WHEN t.type IN (0,1) THEN 1 ELSE 0 END) AS cnt_one_and_zero
, SUM(1) AS cnt_all
FROM mytable t
;
To get the same handling of NULL values and the same result as the first query in this answer, we could write it like this:
SELECT SUM(CASE WHEN t.type=0 THEN 1 WHEN t.type IS NULL THEN NULL ELSE 0 END) AS cnt_zero
, SUM(CASE WHEN t.type=1 THEN 1 WHEN t.type IS NULL THEN NULL ELSE 0 END) AS cnt_one
, SUM(CASE WHEN t.type IN (0,1) THEN 1 WHEN t.type IS NULL THEN NULL ELSE 0 END) AS cnt_one_and_zero
, SUM(1) AS cnt_all
FROM mytable t
;
In all of these, the theme remains the same: we're aggregating the results of a condition. Aka conditional aggregation.
GROUP BY does exactly this:
SELECT type, COUNT(*) AS count_of_type FROM my_table GROUP BY type
This would give you multiple rows, one per type:
+------+---------------+
| type | count_of_type |
+------+---------------+
| 0 | 2 |
| 1 | 3 |
+------+---------------+
If you have more types, but only want 0 and 1, you may add a HAVING clause:
SELECT type, COUNT(*) AS count_of_type FROM my_table GROUP BY type HAVING type IN (0,1)
If you prefer to get different counts in a single result-set-row, please see the answer by spencer7593.
Very simple:
SELECT
`type`,
count(*) as `typecount`
FROM table
GROUP BY `type`
I wanted to count and sum all of bits column in my table if the sum of it is greater than 2 the isApprove column in my documents table will be 1.
SELECT document_id,
SUM(CASE WHEN isApprove = 1 THEN 1 ELSE 0 END) AS approveBy
FROM approvals_document
Output:
document_id | approveBy
96 2
I wanted to join the related table for approvals_document which is documents using this.
SELECT document_id, D.isApprove,
SUM(CASE WHEN isApprove = 1 THEN 1 ELSE 0 END) AS approveBy
FROM approvals_document AD
INNER JOIN documents D ON D.id = AD.document_id
But it won't join the isApprove column. Which part am I missing? Any help would appreciated!
approvals_document column
id | document_id | isApprove
documents column
id | isApprove
Draft output:
document_id | approveBy | isApprove(documents table)
96 2 0
Youre missing an equals in the join clause, in the ON, and you need to alias the case:
SELECT document_id, D.isApprove,
SUM(CASE WHEN AD.isApprove = 1 THEN 1 ELSE 0 END) AS approveBy
FROM approvals_document AD
INNER JOIN documents D ON D.id = AD.document_id
Try with the below query using LEFT JOIN AND GROUP BY.
SELECT d.id,
d.isApprove,
SUM(CASE WHEN ad.document_id IS NULL THEN 0 ELSE 1 END) AS approveBy
FROM documents d
LEFT JOIN approvals_document ad
ON ad.isApprove =1 and ad.document_id = d.id
GROUP BY d.id,d.isApprove
You are trying to list all documents and number of approvedBy:
try:
SELECT documents.id,
documents.isApprove,
(select count(*) from approvals_document WHERE approvals_document.isApprove =1 and approvals_document.document_id = documents.id) as approveBy
FROM documents;
will give you
+------------+--------------------+--------------------------+
| documet.id | isapproved or not, | number of times approved |
+------------+--------------------+--------------------------+
| 1 | 1 | 2 |
+------------+--------------------+--------------------------+
I am new to sql and i have this problem in hand.
I have a table temp which has id and flag as its columns.
ID FLAG
-- ----
A 1
A 1
A 0
B 1
B 0
B 0
C 0
C 0
C 0
I need the 1's and 0's count with respect to each ID.
The desired output is
ID OnesCount ZerosCount
--- --------- ----------
A 2 1
B 1 2
C 0 3
I tried a lot i can get them individually by
select id,count(*) ZerosCount from temp where flag = 0 group by id
select id,count(*) OnesCount from temp where flag = 1 group by id
But do not understand how to join and get the desired output.
Can some one please help
In this specific case you can do like this:
select customer_id ID,
sum(pwr_flag) OnesCount,
sum(1-pwr_flag) ZerosCount
from temp_pwr
group by customer_id
In a more generic case you can use case when:
select customer_id ID,
sum(case pwr_flag when 1 then 1 else 0 end) OnesCount,
sum(case pwr_flag when 0 then 1 else 0 end) ZerosCount
sum(case pwr_flag when 17 then 1 else 0 end) SeventeensCount
from temp_pwr
group by customer_id
select customer_id,
count(case when pwr_flag = 0 then 1 end) ZerosCount,
count(case when pwr_flag = 1 then 1 end) OnessCount
from temp_pwr
group by customer_id
I have a table that has this structure:
table
id | site_id
-------------------
240 | 1
240 | 2
240 | 3
320 | 1
320 | 2
421 | 1
520 | 2
-------------------
300k records
Now i am trying to write a query to return a yes or a no for each record (id).
For example if the records with id 240 only have a site_id 1 then return 'Yes', if it has 2, 3 and so on return 'No'
I am not sure how to approach it but here is a result sample:
result_table
.-----------------------.
| id | result |
|-----------------------|
| 240 | No | -- has a site_id 1, 2 and 3
| 320 | No | -- has a site_id 1 and 2
| 421 | Yes | -- has a site_id 1 only
| 520 | No | -- has a site_id 2
'-----------------------'
Here is the query i have so far, but it seems to be incorrect
SELECT CASE WHEN count(id) > 1 THEN 'N' ELSE 'Y' END as Result
FROM table sm
WHERE sm.site_id IN (1)
AND sm.site_id NOT IN (2,3,4,5,6,7,8,9)
AND id = 240
UPDATE
SO Here is my full query, i added the answer from #gordon
SELECT
m.merchant_name,
m.merchant_id,
ut.realname,
a.affiliate_name,
(select (case when count(site_id) = 1 then 'Yes' else 'No' end) as result
from site_merchant sm
WHERE sm.merchant_id = m.merchant_id
group by merchant_id) as isTjoos, -- y or no
(select (case when count(site_id) = 2 then 'Yes' else 'No' end) as result
from site_merchant sm
WHERE sm.merchant_id = m.merchant_id
group by merchant_id) as isUCOnly
-- isdlkonly -- y or no
FROM merchant m
LEFT JOIN merchant_editor_assignment mea ON mea.merchant_id = m.merchant_id
LEFT JOIN user_table ut ON ut.user_id = mea.user_id
LEFT JOIN affiliate a ON a.affiliate_id = m.affiliate_id_default
I interpreted this question as you want ids that have only one value for site_id. I took the example in the question to be an example, with site_id = 1. To do this:
You want to use count(distinct):
select id, (case when count(distinct site_id) = 1 then 'Yes' else 'No' end) as result
from site_merchant sm
group by id
A slightly more efficient version is to use min() and max(), assuming that the site_id is never NULL:
select id, (case when min(site_id) = max(site_id) then 'Yes' else 'No' end) as result
from site_merchant sm
group by id
This is because min and max generally require a bit less processing than count(distinct).
If you want to check that the site_id is "1" and never anything else, then add the condition and min(site_id) = 1 to the when clause.
If you want to check that the site_id is 1 and there is exactly one row, then you can do:
select id, (case when count(site_id) = 1 and min(site_id) = 1 then 'Yes' else 'No' end) as result
from site_merchant sm
group by id
And, if you want to check that there is exactly one row:
select id, (case when count(site_id) = 1 then 'Yes' else 'No' end) as result
from site_merchant sm
group by id
SELECT
it,
CASE WHEN COUNT(CASE WHEN site_id THEN 1 END)=1
AND COUNT(CASE WHEN site_id!=1 THEN 1 END)=0 THEN 'Yes'
ELSE 'No'
END
FROM sm
GROUP BY it
Please see fiddle here.
SELECT ID, CASE WHEN EXTRA > 1 THEN 'No' ELSE 'Yes' END AS Result
FROM
(SELECT ID, Sum(site_id) AS Extra
from myTable
GROUP BY ID
) AS Test
EDIT: I suppose this should work in MySQL. I haven't worked on it though.
The idea is to SUM up the site_id. For records with only site_id = 1, the sum will be 1.
Your query seems overcomplicated. Just to start, why the IN(1) and NOT IN(2,3...9)? And why limit to a single ID (AND id = 240) when your "result sample" clearly doesn't want that? It does not make any sense. How about this?
SELECT CASE WHEN count(merchant_id) > 1 THEN 'N' ELSE 'Y' END as isTjoos
FROM site_merchant
GROUP BY site_id;
I would use a Having Count Statement. Something like that:
SELECT site_id
FROM site_merchant
HAVING (count(merchant_id) > 1)
GROUP BY site_id;
Here is the solution i found. I used #Gordons query to get started and what was missing was the site_id, and the group by was not needed:
SELECT
m.merchant_name,
m.merchant_id,
ut.realname,
a.affiliate_name,
(select (case when count(*)>0 then 'No' else 'Yes' end) as result
from site_merchant sm
WHERE sm.merchant_id = m.merchant_id
AND site_id != 1) as isTjoos,
(select (case when count(*)> 0 then 'No' else 'Yes' end) as result
from site_merchant sm
WHERE sm.merchant_id = m.merchant_id
AND site_id != 2) as isUCOnly,
(select (case when count(*)> 0 then 'No' else 'Yes' end) as result
from site_merchant sm
WHERE sm.merchant_id = m.merchant_id
AND site_id != 3) as isDLKonly
FROM merchant m
LEFT JOIN merchant_editor_assignment mea ON mea.merchant_id = m.merchant_id
LEFT JOIN user_table ut ON ut.user_id = mea.user_id
LEFT JOIN affiliate a ON a.affiliate_id = m.affiliate_id_default
Thank you for the help.
I have a table like this:
id|category
where category is an integer between 0 and 3. How do I count how many rows are in each category. Is it possible in a single query?
F.x. if I have these rows:
a|3
b|1
d|1
f|0
g|2
the result shoud be:
(1,2,1,1)
ie. 1 in category = 0, 2 in category = 1 etc.
This will get you a row for each category.
SELECT category, COUNT(*) as catcount
FROM YourTable
GROUP BY category
To get output in the exact format you specified (1 row, 4 columns):
SELECT SUM(CASE WHEN category = 0 THEN 1 ELSE 0 END) AS cat0count,
SUM(CASE WHEN category = 1 THEN 1 ELSE 0 END) AS cat1count,
SUM(CASE WHEN category = 2 THEN 1 ELSE 0 END) AS cat2count,
SUM(CASE WHEN category = 3 THEN 1 ELSE 0 END) AS cat3count
FROM YourTable