I have a sql table like this:
------------------------------------------
ID | SKU | Name | Type
-------------------------------------------
2 | ABC | Pasta | 2
3 | XYZ | Maggi | 5
2 | ABC | Pasta | 5
6 | MNO | Macroni | 2
3 | XYZ | Maggi | 0
3 | XYZ | Maggi | 2
I need to find rows which have type 2 but not have an entry for type 5 or 0
For example: It should result in
------------------------------------------
ID | SKU | Name | Type
-------------------------------------------
6 | MNO | Macroni | 2
Is it possible to result so using this one table only? Of course it is. This table has 1.4M rows and I used this query (not sure if it is correct)
SELECT e1.* FROM reportmal e1, reportmal e2
WHERE e1.id= e2.id
AND e1.type=2 AND e2.type=5
The query never returned anything, because it is still running. Can you help?
I like to do this with having
and group by
:
select e.id
from reportmal e
group by e.id
having sum(e.type = 2) > 0 and
sum(e.type in (0, 5)) = 0;
MySQL treats boolean expressions as integers in a numeric context, with "1" for true and "0" for false. Hence sum(e.type = 2)
counts the number of records in each group where type = 2
. The > 0
means that at least one such row exists. The = 0
means that no such rows exist.
If you want the original rows you can join
this result back to the table.
Sounds like a typical "not exists"-query:
select * from atable result
where result.type = 2 and not exists
(select 1 from atable no50
where no50.type in (5,0)
and no50.sku = result.sku
)
or:
select * from atable result
where result.type = 2 and result.sku not in
(select sku from atable no50
where no50.type in (5,0)
)
Try this using group by
to find the ID which has 2 and not 0 or 5 using conditional count and then using IN
to get the relevant rows.
select *
from your_table
where id in (
select
id
from your_table t
group by id
having count(case when type = 2 then 1 end) > 0
and count(case when type in (0,5) then 1 end) = 0
);
select *
from reportmal e
where e.type = 2
and not exists
(
select null
from reportmal e2
where e2.id = e.id
and e2.type in (0,5)
)
As for the performance issue -
The minimum you need is an index on reportmal (id).
Index on reportmal (id,type) might be better.
I think you should use this:
SELECT a.*
FROM reportmal a
WHERE a.type = 2
AND NOT EXISTS (SELECT 1
FROM reportmal b
WHERE b.name = a.name
AND b.type IN (5,0));
It's like: "All rows with TYPE 2, and NOT EXISTS a row with same NAME and TYPE 5 or 0"
I don't know what's your parameter to define an "entry". Maybe you should add SKU on subquery (it all depends your data model).
Your query was close, but you were joining on Id which will give you a Cartesian product.
This is how I'd do it.
Select p1.*
From pasta p1
Left outer join pasta p2 on p1.sku=p2.sku
And p2.type in (0,5)
Where p2.type is null
Hope that helps you.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.