MySQL query that find matches that are ecual [duplicate] - mysql

This question already has answers here:
How to return rows that have the same column values in MySql
(3 answers)
Closed 6 years ago.
I have the following MySQL table called "MyTable"
ID--- a --- b
10---20---42
11---20---43
12---20---44
13---21---44
14---20---45
14---22---44
14---22---43
14---24---45
14---22---42
I am trying to write a query that gets me into the following results.
Examples.
SELECT b FROM mytable WHERE a=(20, 21, 22)
This returns 44 as it is the only number that is common.
SELECT b FROM mytable WHERE a=(20, 22) AND b is the same
This returns 42 and also 43 because both match
SELECT b FROM mytable WHERE a=(22, 24) AND b is the same
This returns nothing because the b value is different between the numbers in column a.
Thanks for your help
(found an answer I guess)
select b
from MyTable
group by b
having sum(a = 20) > 0 and // -- has id = 20
sum(a = 21) > 0 // -- has id = 21

For queries like that where you want to narrow down by a set you can do it one of two ways, the long way:
SELECT b FROM mytable WHERE a=20 OR a=21 OR a=22
Or the short way, by using the IN keyword:
SELECT b FROM mytable WHERE a IN (20, 21, 22)
for your query 'SELECT b FROM mytable WHERE a=(20, 22) AND b is the same' you can still use the same idea, but do:
SELECT b FROM mytable WHERE a IN(20, 22) AND b=a

Related

query to get records with exact values of a field [duplicate]

This question already has answers here:
SELECTING with multiple WHERE conditions on same column
(12 answers)
Closed 4 years ago.
I have a mysql table like this:
id_doc | id_category
1 a
1 c
1 f
2 a
2 g
3 a
3 b
3 f
4 h
I need a query to extract docs that have categories "a" and "f".
example:
id_doc
1
3
please help me!
Thanks
Aggregate and use HAVING to check if the number of distinct groups a document is in equals 2.
SELECT id_doc
FROM document_category
WHERE id_category IN ('a',
'f')
GROUP BY id_doc
HAVING count(DISTINCT id_category) = 2;
Or, if you have a documents table use two EXISTS.
SELECT d.id_doc
FROM document d
WHERE EXISTS (SELECT *
FROM document_category dc
WHERE dc.id_doc = d.id_doc
AND dc.id_category = 'a')
AND EXISTS (SELECT *
FROM document_category dc
WHERE dc.id_doc = d.id_doc
AND dc.id_category = 'f');

Having trouble with a SQL join

I'm having a bit of a time trying to make this work...
I have one table that uses 1 or 2 digits for the week #. ( 1 to 52)
I have another table that uses 1 or 2 digits for the week# but also has the 2 digit year attached ( 117, 1017, 2217 etc.) ( 117 to 5217)
This is the only field that I can use to join these tables.
How can I join tableA with tableB on 1 = 117 or 12 = 1217...etc.?
The year portion can be omitted.
Give this a shot
SELECT a.Col1,b.Col1
FROM tablea a
JOIN tableb b ON (
(LEN(b.Col1) = 3 AND a.Col1 = LEFT(b.Col1,1))
OR
(LEN(b.Col1) = 4 AND a.Col1 = LEFT(b.Col1,2))
)
This is assuming your datatypes are (n)varchar. If they are INT or other numeric type you'll have to cast in the join clause.

MySQL query to find ids that do not exist in table

I have a list of ids pre-generated that I need to check if exist in a table. My table has two columns, id, name, where id is an auto increment integer and name is a varchar(255).
I basically want to get a count of how many ids do not exist in table foo from my pre-generated list. So say my list has the numbers 5 and 10 in it, what's the best way to write something to the extent of:
select count(*) from foo where id does not exist in ( 5, 10 )
The idea here is that if 5 and 10 do not exist, I need the response 2, and not the number of rows in foo that do not have the id 5 or 10.
TL; DR sample data and queries at rextester
The idea here is that if 5 and 10 do not exist, I need the response 2, and not the number of rows in foo that do not have the id 5 or 10.
You should have provided a little more information to avoid confusion.
Example
id | name
1 | tom
2 | joe
3 | mae
4 | goku
5 | vegeta
If your list contains (1, 2, 3) then your answer should be 0 (since all three are in the table )
If your list contains (1, 2, 6) then your answer should be 1. ( since 1 and 2 are in the table but 6 is in't )
If your list contains (1, 6, 7) then your answer should be 2.
If your list contains (6, 7, 8) then your answer should be 3.
assuming this was your question
If you know the length of your list
select 2 - count(*) as my_count from foo where id in (5, 10)
The following query tells you how many are present in foo.
select count(*) from foo where id in (5,10)
So if you want to find those that do not exist, subtract this result from the length of your list.
select n - count(*) as my_count from foo where id in (5, 10,....)
You could use on fly table using union and the a left join
select count(*)
from my_table as m
left join (
select 5 as id from dual
union
select 10 from dual ) t on t.id = m.id
where t.id is null
otherwise you can populate a tempo table with the value you need and use left join
where the value is null

Is there better way to do this query?

SELECT *
FROM a
WHERE a.re_id = 3443499
AND a.id IN
(
SELECT b.rsp_id FROM b
WHERE b.f_id = 9
GROUP BY b.rsp_id
HAVING FIND_IN_SET(16, GROUP_CONCAT(b.o_id)) > 0
AND FIND_IN_SET(15, GROUP_CONCAT(b.o_id)) > 0
UNION
SELECT b.rsp_id FROM b
WHERE b.f_id = 4
GROUP BY b.rsp_id
HAVING FIND_IN_SET(5, GROUP_CONCAT(b.o_id)) > 0
)
ORDER BY id DESC
Here "f_id" is array and its values are those in first parameter of "FIND_IN_SET" function.
For example
9=>(
16,
15
),
4=>(
5
)
Sample data for those 2 folumns in table b, 2 columns f_id and o_id
f_id o_id
9 15
9 18
9 23
4 5
3 8
The gist of this answer is that the current query does not run. So, fix the syntax and ask another question.
First, you could write the query so it is syntactically correct. The query will fail as written, because the first subquery returns at least two rows and the second only one.
Second, use UNION ALL instead of UNION, unless you specifically want to incur the overhead of removing duplicates.
Third, the ORDER BY will generate an error.
Fourth, the GROUP_CONCAT() is dangerous and unnecessary.
I'm not 100% sure this is the intention, but I would start with a query like this:
SELECT a.id, a.re_id
FROM a
WHERE a.re_id = 3443499 AND
a.id IN (SELECT b.rsp_id
FROM b
WHERE b.f_id = 9
GROUP BY b.rsp_id
HAVING MAX(b.o_id = 16) > 0 AND
MAX(b.o_id = 15) > 0
)
UNION ALL
SELECT b.rsp_id, NULL
FROM b
WHERE b.f_id = 4
GROUP BY b.rsp_id
HAVING MAX(b.o_id = 5) > 0
ORDER BY id;
Then, if you want this optimized, I would suggest asking another question, along with relevant information about the table structures and current performance.

Count first occurence with column value ordered by another column

I have an assigns table with the following columns:
id - int
id_lead - int
id_source - int
date_assigned - int (this represents a unix timestamp)
Now, lets say I have the following data in this table:
id id_lead id_source date_assigned
1 20 5 1462544612
2 20 6 1462544624
3 22 6 1462544615
4 22 5 1462544626
5 22 7 1462544632
6 25 6 1462544614
7 25 8 1462544621
Now, lets say I want to get a count of the rows whose id_source is 6, and is the first entry for each lead (sorted by date_assigned asc).
So in this case, the count would = 2, because there are 2 leads (id_lead 22 and 25) whose first id_source is 6.
How would I write this query so that it is fast and would work fine as a subquery select? I was thinking something like this which doesn't work:
select count(*) from `assigns` where `id_source`=6 order by `date_assigned` asc limit 1
I have no idea how to write this query in an optimal way. Any help would be appreciated.
Pseudocode:
select rows
with a.id_source = 6
but only if
there do not exist any row
with same id_lead
and smaller date_assigned
Translate it to SQL
select * -- select rows
from assigns a
where a.id_source = 6 -- with a.id_source = 6
and not exists ( -- but only if there do not exist any row
select 1
from assigns a1
where a1.id_lead = a.id_lead -- with same id_lead
and a1.date_assigned < a.date_assigned -- and smaller date_assigned
)
Now replace select * with select count(*) and you'll get your result.
http://sqlfiddle.com/#!9/3dc0f5/7
Update:
The NOT-EXIST query can be rewritten to an excluding LEFT JOIN query:
select count(*)
from assigns a
left join assigns a1
on a1.id_lead = a.id_lead
and a1.date_assigned < a.date_assigned
where a.id_source = 6
and a1.id_lead is null
If you want to get the count for all values of id_source, the folowing query might be the fastest:
select a.id_source, count(1)
from (
select a1.id_lead, min(a1.date_assigned) date_assigned
from assigns a1
group by a1.id_lead
) a1
join assigns a
on a.id_lead = a1.id_lead
and a.date_assigned = a1.date_assigned
group by a.id_source
You still can replace group by a.id_source with where a.id_source = 6.
The queries need indexes on assigns(id_source) and assigns(id_lead, date_assigned).
Simple query for that would be
check here http://sqlfiddle.com/#!9/8666e0/7
select count(*) from
(select * from assigns group by id_lead )t
where t.id_source=6