I'm trying to achieve something very similar to SQL - Multiple conditions where clause the same column
The difference is that I want two separate WHERE conditions:
WHERE tag_id IN (1,2)
OR tag_id IN (3,2)
GROUP BY other_id HAVING COUNT(tag_id) = 2
This gives me all the records that I need, but also gives me records that have the tags 1 or 3 even when that record doesn't have tag_id = 2. I know that my problem is in the OR condition, because if I do (1,2) and (3,2) separately, I get the expected results for each query.
What am I missing?
You could use:
SELECT other_id
FROM yourTable
GROUP BY other_id
HAVING COUNT(tag_id) = 2 AND -- 2 tags
(SUM(tag_id NOT IN (1, 2)) = 0 OR -- either (1, 2)
SUM(tag_id NOT IN (3, 2)) = 0); -- or (3, 2)
Related
I have a table with an id column and a source column.
I want to return only the source values that all ids share.
E.g. in the table below id 1,2,3 all share 10 and 20, but id 3 is missing the source value 30, so 30 is not valid and I want to return 10 and 20.
I'm using MySQL and want to put this in a stored procedure.
How do I do this?
id
source
1
10
1
20
1
30
2
10
2
20
2
30
3
10
3
20
You may use COUNT(DISTINCT) function as the following:
SELECT source FROM
table_name
GROUP BY source
HAVING COUNT(DISTINCT id)=(SELECT COUNT(DISTINCT id) FROM table_name)
To do this within a stored procedure:
CREATE PROCEDURE getSourceWithAllIds()
BEGIN
SELECT source FROM
table_name
GROUP BY source
HAVING COUNT(DISTINCT id)=(SELECT COUNT(DISTINCT id) FROM table_name);
END
The idea is to select the count of distinct id values for each source, which is done by COUNT(DISTINCT id)... GROUP BY source, then match this count with the distinct count of all id values existed in the table; HAVING COUNT(DISTINCT id)=(SELECT COUNT(DISTINCT id) FROM table_name).
If the two counts are equal, then the source have all the distinct ids existed in the table.
i.e. All distinct ids in the table are (1, 2, 3) count = 3, and distinct ids for a source =10 are (1, 2, 3) count=3. For source = 30, the distinct ids are (1, 2) count=2 so it will not be returned by the query (2<>3).
See a demo.
I have this query:
SELECT (COUNT(*) = SUM(status in (3, 5)) ) AS result
FROM `match` WHERE round_id = 15
this essentially check if the table match have all the items with a status 3 or 5 for the round 15. This works, but I actually want add another condition, in particular if the result is true I want check that all the records of that table with round_id = 15 are 20. How can I perform this?
Is this what you want?
SELECT (COUNT(*) = SUM(status in (3, 5)) AND COUNT(*) = 20) AS result
FROM `match`
WHERE round_id = 15;
This checks that there are 20 rows that match the conditions.
Please take a look at this fiddle.
I'm working on a search filter select box and I want to insert the field names of a table as rows.
Here's the table schemea:
CREATE TABLE general
(`ID` int, `letter` varchar(21), `double-letters` varchar(21))
;
INSERT INTO general
(`ID`,`letter`,`double-letters`)
VALUES
(1, 'A','BB'),
(2, 'A','CC'),
(3, 'C','BB'),
(4, 'D','DD'),
(5, 'D','EE'),
(6, 'F','TT'),
(7, 'G','UU'),
(8, 'G','ZZ'),
(9, 'I','UU')
;
CREATE TABLE options
(`ID` int, `options` varchar(15))
;
INSERT INTO options
(`ID`,`options`)
VALUES
(1, 'letter'),
(2, 'double-letters')
;
The ID field in options table acts as a foreign key, and I want to get an output like the following and insert into a new table:
id field value
1 1 A
2 1 C
3 1 D
4 1 F
5 1 G
6 1 I
7 2 BB
8 2 CC
9 2 DD
10 2 EE
11 2 TT
12 2 UU
13 2 ZZ
My failed attempt:
select DISTINCT(a.letter),'letter' AS field
from general a
INNER JOIN
options b ON b.options = field
union all
select DISTINCT(a.double-letters), 'double-letters' AS field
from general a
INNER JOIN
options b ON b.options = field
Pretty sure you want this:
select distinct a.letter, 'letter' AS field
from general a
cross JOIN options b
where b.options = 'letter'
union all
select distinct a.`double-letters`, 'double-letters' AS field
from general a
cross JOIN options b
where b.options = 'double-letters'
Fiddle: http://sqlfiddle.com/#!2/bbf0b/18/0
A couple to things to point out, you can't join on a column alias. Because that column you're aliasing is a literal that you're selecting you can specify that literal as criteria in the WHERE clause.
You're not really joining on anything between GENERAL and OPTIONS, so what you really want is a CROSS JOIN; the criteria that you're putting into the ON clause actually belongs in the WHERE clause.
I just made this query on Oracle.
It works and produces the output you described :
SELECT ID, CASE WHEN LENGTH(VALUE)=2THEN 2 ELSE 1 END AS FIELD, VALUE
FROM (
SELECT rownum AS ID, letter AS VALUE FROM (SELECT DISTINCT letter FROM general ORDER BY letter)
UNION
SELECT (SELECT COUNT(DISTINCT LETTER) FROM general) +rownum AS ID, double_letters AS VALUE
FROM (
SELECT DISTINCT double_letters FROM general ORDER BY double_letters)
)
It should also run on Mysql.
I did not used the options table. I do not understand his role. And for this example, and this type of output it seems unnecessary
Hope this could help you to.
Below is my table, how can i get the item_id with selecting multiple item_subcategory_id.
For example i need to get the item_id with an item_subcategory_id of 86,51 and 1. I should only get the item_id 1 even though item_id 2 has an item_subcategory_id of 51
Please note that the number of item_subcategory_id is dynamic.
I tried the query
SELECT item_id
FROM item_specs
WHERE item_subcategory_id = 86 AND
item_subcategory_id=51 AND
item_subcategory_id = 1
but it displays an empty result
You can use the count and compare the result of count to the no of distinct item_subcategory_ids you provide in in() clause like in your case distinct item_subcategory_ids is 3 ,so this will result only those item_ids which has all of these provided item_subcategory_ids
select * from table
where item_subcategory_id in(1,51,86)
group by item_id
having count(distinct item_subcategory_id) =3
Use AND operator to combine your conditions
select item_category_id
from mytable
where item_id = 1 and item_subcategory_id in (86, 51, 1);
I would like to select multiple values from a single column in a database table that equal to a number of values. I want all these values to match otherwise it should return no rows. I do not want to use "IN" as that is equal to "OR".
The following is a basic mockup of what it should do but it needs to be dynamic as I wish to use it with a PDO statement. If the database only contains id's 1 and 2 it should fail ie return no rows.
SELECT
id
FROM
reports
WHERE
id=1 AND id=2 AND id=3
I have the current code as follow which is incorrectly returning zero rows:
SELECT id,title
FROM reports
WHERE id IN (1,2)
GROUP BY title
HAVING COUNT(DISTINCT id) = 2
My current table structure is as follows:
http://www.sqlfiddle.com/#!2/ce4aa/1
You have to use HAVING COUNT(id) = 3 to ensure that the selected rows have all the three id's. Something like:
SELECT *
FROM reports
WHERE id = 1 OR id = 2 OR id = 3 -- Or id IN(1, 2, 3)
GROUP BY SomeOtherField
HAVING COUNT(DISTINCT id) = 3;
Or:
SELECT *
FROM reports
WHERE SomeOtherField IN (SELECT SomeOtherField
FROM reports
WHERE id = 1 or id = 2 -- Or id IN(1, 2, 3)
GROUP BY SomeOtherField
HAVING COUNT(DISTINCT id) = 3
);
Note that: You have to GROUP BY SomeOtherField where SomeOtherField is other field than id because if you GROUP BY id with HAVING COUNT(id) you won't get any records, since COUNT(id) will be always = 1.
Edit: fixed WHERE clause, OR's instead of AND's.
SQL Fiddle Demo