I have a table with 3 columns looking like this :
id
key
status
1
1
a
2
2
a
3
3
a
4
1
b
5
2
b
6
4
b
I want to extract rows where a key have a "a" AND a "b" as status...
id
key
status
1
1
a
2
2
a
4
1
b
5
2
b
I KNOW that I need some GROUP BY and HAVING but I twisted my brain for few hours and I don't find any solution...
Thanx !
You can use having count
select `key`
from my_table
where status in ('a','b')
group by `key`
having count(distinct status) =2;
If you need the other values you can use inner join with subquery
select m.*
from my_table m
inner join (select `key`
from my_table
where status in ('a','b')
group by `key`
having count(distinct status) =2
) tbl on m.`key`=tbl.`key`;
https://dbfiddle.uk/yq5OiPtU
Related
I have a table like this:
**lead_id** **form_id** **field_number** **value**
1 2 1 Richard
1 2 2 Garriot
2 2 1 Hellen
2 2 2 Garriot
3 2 1 Richard
3 2 2 Douglas
4 2 1 Tomas
4 2 2 Anderson
Where field_number = 1 is the name and field_number = 2 is the surname.
I would like to find entries that are equal by name OR surname and group them by lead_id, so the output could be like this:
1
2
3
Any thoughts on how this can be done?
This should work and be reasonably efficient (depending upon indexes):
select distinct lead_id
from tablename as t1
where exists (
select 1
from tablename as t2
where t1.field_number = t2.field_number
and t1.value = t2.value
and t1.lead_id <> t2.lead_id
)
Select leadid from (
Select DISTINCT leadid,value from tablename
Where fieldnumber=1
Group by leadid,value
Having count(value) >1
Union all
Select DISTINCT leadid,value from tablename
Where fieldnumber=2
Group by leadid,value
Having count(value) >1
) as temp
Surely there is a faster option
I am searching an addresses table for duplicates, using SOUNDEX to find the duplicates. This works fine, and it requires all 5 soundex columns to match in order to group
However, I want to GROUP where ANY 3 of my 5 SOUNDEX columns match.
Here is my current query:
SELECT `Address`.`id`,
SOUNDEX(`Address`.`address_company_name`) as soundex_address_company_name,
SOUNDEX(`Address`.`contact_name`) as soundex_contact_name,
SOUNDEX(`Address`.`street_address`) as soundex_street_address,
SOUNDEX(`Address`.`suburb`) as soundex_suburb,
SOUNDEX(`Address`.`city`) as soundex_city,
`Address`.`address_country_id`,
`Address`.`address_zone_id`,
`Address`.`postcode`,
COUNT(*)
FROM
`addresses` AS `Address`
WHERE
((`Address`.`address_company_name` IS NOT NULL)
OR (`Address`.`contact_name` IS NOT NULL))
GROUP BY
SOUNDEX(address_company_name),
SOUNDEX(contact_name),
SOUNDEX(street_address),
SOUNDEX(suburb),
SOUNDEX(city),
address_country_id,
address_zone_id,
postcode
HAVING
COUNT(*) > 1
I understand how to do this with multiple queries, ie: loop through each address in our database and then re-query the database for addresses which match any 3 of the 5 columns, however I am hoping to do this in fewer queries as the above query executes very quickly.
I also understand that were this possible, some records may be grouped multiple times, I don't mind if this is the case but I am unsure whether this flies in the face of MySQL logic?
You can try something like this
SELECT a.id, b.id id2, COUNT(*) no_matches
FROM
(
SELECT id,
column_id,
CASE column_id
WHEN 1 THEN SOUNDEX(address_company_name)
WHEN 2 THEN SOUNDEX(contact_name)
WHEN 3 THEN SOUNDEX(street_address)
WHEN 4 THEN SOUNDEX(suburb)
WHEN 5 THEN SOUNDEX(city)
END column_value
FROM addresses a CROSS JOIN
(
SELECT 1 column_id UNION ALL
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4 UNION ALL
SELECT 5
) i
WHERE address_company_name IS NOT NULL
OR contact_name IS NOT NULL
) a CROSS JOIN
(
SELECT id,
column_id,
CASE column_id
WHEN 1 THEN SOUNDEX(address_company_name)
WHEN 2 THEN SOUNDEX(contact_name)
WHEN 3 THEN SOUNDEX(street_address)
WHEN 4 THEN SOUNDEX(suburb)
WHEN 5 THEN SOUNDEX(city)
END column_value
FROM addresses a CROSS JOIN
(
SELECT 1 column_id UNION ALL
SELECT 2 UNION ALL
SELECT 3 UNION ALL
SELECT 4 UNION ALL
SELECT 5
) i
WHERE address_company_name IS NOT NULL
OR contact_name IS NOT NULL
) b
WHERE a.column_value = b.column_value
AND a.id < b.id
GROUP BY a.id, b.id
HAVING COUNT(*) > 2
Sample output:
| ID | ID2 | NO_MATCHES |
|----|-----|------------|
| 1 | 2 | 4 |
| 4 | 5 | 3 |
Here is SQLFiddle demo
Ok I have siple table which contains data:
id cat_id title (with random values)
1 1 test
2 1 tstt
3 3 tewt
4 2 4324
5 3 rterter
Now, I need to create a query which selects only ONE raw per category (cat_id)
(possibly with lowest ID and ordered by cat_id)
So the result should be:
1 1 test
4 2 4324
3 3 tewt
Use GROUP BY :
SELECT MIN(id), cat_id, title FROM table GROUP BY cat_id
SELECT a.*
FROM tableName a
INNER JOIN
(
SELECT cat_id, MIN(id) id
FROM tableName
GROUP BY cat_id
) b ON a.cat_id = b.cat_id AND
a.id = b.id
ORDER BY a.cat_id
I am writing a query to grab the items that a specific user_id was the first to use. Here is some sample data -
item_id used_user_id date_used
1 1 2012-08-25
1 2 2012-08-26
1 3 2012-08-27
2 2 2012-08-27
3 1 2012-08-27
4 1 2012-08-21
4 3 2012-08-24
5 3 2012-08-23
query
select item_id as inner_item_id, ( select used_user_id
from test
where test.item_id = inner_item_id
order by date_used asc
limit 1 ) as first_to_use_it
from test
where used_user_id = 1
group by item_id
It returns the correct values
inner_item_id first_to_use_it
1 1
3 1
4 1
but the query is VERY slow on a giant table. Is there a certain index that I can use or a better query that I can write?
i can't get exactly what you mean because in your inner query you have sorted it by their used_user_id and and on your outer query you have filtered it also by their userid. Why not do this directly?
SELECT DISTINCT item_id AS inner_item_id,
used_user_id AS first_to_use_it
FROM test
WHERE used_user_id = 1
UPDATE 1
SELECT b.item_id,
b.used_user_id AS first_to_use_it
FROM
(
SELECT item_ID, MIN(date_used) minDate
FROM tableName
GROUP BY item_ID
) a
INNER JOIN tableName b
ON a.item_ID = b.item_ID AND
a.minDate = b.date_used
WHERE b.used_user_id = 1
I have two tables:
builders
b_id fk_c_id
1 1
2 1
3 1
4 1
5 1
6 2
7 2
subbuilders
fk_b_id sb_id
1 2
1 3
1 4
2 5
6 7
and i want Distinct b_id which are not exist in subbuilders table and must have same fk_c_id
I create:
SELECT DISTINCT b.id FROM pms_builder_to_subbuilders bsb
LEFT JOIN pms_builders b ON b.id = bsb.sb_id WHERE b.fk_c_id = '1'
but it show Distinct records from subbuilders.
You can get the desired results with the following query:
SELECT DISTINCT b.b_id FROM builders b LEFT JOIN subbuilders sb ON sb.fk_b_id = b.b_id WHERE b.fk_c_id = '1' AND ISNULL(fk_b_id);
i think you want this query:
SELECT DISTINCT b_ID
FROM builders
WHERE b_ID NOT IN
(SELECT DISTINCT fk_b_id FROM subbuilders)
but it returns
b_ID
========
3
4
5
7
but i didn't understand your statement: must have same fk_c_id. What do you mean by that?
b_id = fk_c_id
if that's the case then there will be no rows returned because only record 1 has the same b_ID and fk_c_id but exists in table subbuilders