This is my table structure for product
product_id product_name
---------------------------------
100 Mouse
101 Keyboard
101 Pendrive
102 Motherboard
102 Card Reader
103 Adapter
I want the query which will give me following output by eliminating the duplicate record
OUTPUT
------------------
100
103
I have tried this query
SELECT count(product_id)
FROM product
GROUP BY product_id
Try this:
SELECT product_id
FROM product
GROUP BY product_id
HAVING COUNT(product_id) = 1;
You can try this SQL
SELECT t1.product_id FROM (SELECT product_id, COUNT(*) AS cnt FROM table GROUP BY product_id) t1 WHERE t1.cnt = 1
Related
I am using mariadb and I have a table called links:
id | product_id | last_change
------------------------------
1 1 xxx
2 2 xxx
3 5 xxx
4 5 xxx
I want to find every object (3, 4 in this example) that occures more than once. Following this answer I tried:
SELECT product_id, COUNT(*) from links HAVING COUNT(*) > 1
But this results in the (adapted to this example) first row being shown and the total number of product_id occurrences:
product_id | COUNT(*)
---------------------
1 4
I wanted to achieve a list of all items occuring more than once:
id | product_id | last_change
------------------------------
3 5 xxx
4 5 xxx
An aggregation function without GROUP BY always results in only one row result as it aggregates all rows
So use a GROUP BY
SELECT product_id, COUNT(*) from links GROUP BY product_id HAVING COUNT(*) > 1
To see all entry with the count of the product_id , you can do following
SELECT l1.product_id , last_change , Count_
FROM links l1
JOIN (SELECT product_id, COUNT(*) as Count_ from links GROUP BY product_id HAVING COUNT(*) > 1) l2
ON l1.product_id = l2.product_id
Try below statement
select id, product_id, count(product_id)
from links
group by (product_id)
having count(product_id)> 1;
I have a complex query joined to multiple tables to show a "transaction history", I want a quick and easy way to count the occurrences of order_id to make it as the line_number. I had it done with code but for performance reason I want to have it done with MySQL. Here is an example of what I have:
order_id item_id
--------- --------
1111111 444444
1111111 555555
1111111 666666
1111112 123333
1111112 121111
1111113 123123
1111114 123123
1111115 123123
This is what I want it to look like:
order_id line_number item_id
--------- ------------ ---------
1111111 1 444444
1111111 2 555555
1111111 3 666666
1111112 1 123333
1111112 2 121111
1111113 1 123123
1111114 1 123123
1111115 1 123123
I tried COUNT(order_id) but that didn't work, unless there is a good way to do it. Thanks!
MySQL version 5.5.43
In MySQL 8.0, just use row_number():
select
order_id,
row_number() over(partition by order_id order by item_id) line_number,
item_id
from mytable
order by order_id, item_id
In earlier versions, one solution (other than using variables) is to do an inline count with a subquery:
select
order_id,
(
select 1 + count(*)
from mytable t1
where t1.order_id = t.order_id and t1.item_id < t.item_id
) line_number,
item_id
from mytable t
order by order_id, item_id
There is probably a simple answer to this but I can't seem to find it anywhere..
My table looks like this:
item_id tag_id
----------------------
100 55
101 55
100 320
102 320
100 77
100 489
101 200
Asking for items with tags 55 AND 320 should return item_id = 100 (but not 101 or 102 as they don't have both tags)
You could use HAVING clause:
SELECT item_id
FROM tab_name
WHERE tag_id IN (1,2)
GROUP BY item_id
HAVING COUNT(DISTINCT tag_id) = 2;
SqlFiddleDemo
or even:
SELECT item_id
FROM tab_name
GROUP BY item_id
HAVING GROUP_CONCAT(DISTINCT tag_id ORDER BY tag_id ) = '1,2';
SqlFiddleDemo2
You can try:
SELECT item_id
FROM table_name
WHERE tag_id IN (55,320)
GROUP BY item_id
HAVING COUNT(DISTINCT tag_id) > 1;
It will return item_id that have more than one distinct tag_id.
Pass your tags in IN by comma separated as many as you want.
SELECT item_id
FROM Table1
WHERE tag_id IN (55,320)
GROUP BY item_id
HAVING COUNT(DISTINCT tag_id) > 1
Fiddle example
I'm running a query that selects details of orders, and I want to see only the orders that have gone through multiple stages. My data looks like:
id | order_id | action
1 100 1
2 100 2
3 100 4
4 101 1
5 102 2
6 103 1
7 103 2
So that only the rows for order_id 100 and 103 will be selected. This needs to be nested in a larger query.
You can use a subquery to get the orders that had multiple stages:
SELECT order_id
FROM your_table
GROUP BY order_id
HAVING COUNT(*)>1
then you can join this result back to your table:
SELECT o.*
FROM yourtable AS o INNER JOIN (
SELECT order_id
FROM your_table
GROUP BY order_id
HAVING COUNT(*)>1
) dup ON o.order_id = dup.order_id
Use group by with count and having
select *,count(order_id) as total from table
group by order_id
having total > 1
you can try this query:
select * from your_table
where ( select count(*) from your_table internal_table
where your_table .order_id = internal_table.order_id
) > 1
I have a table item_category with two columns: item_id, cat_id. Item to category is a many-to-many relationship.
If my table looks like this...
item_id | cat_id
1 | 1
1 | 2
2 | 3
2 | 4
3 | 5
3 | 6
4 | 7
4 | 8
5 | 9
5 | 10
... how can I select a distinct list of item_ids that do not have any rows where category_id is 2 or 7 (yielding item_ids of 2, 3, 5)?
I would do this using aggregation and a having clause:
select item_id
from item_category ic
group by item_id
having max(cat_id = 2) = 0 and
max(cat_id = 7) = 0
This is an example of a "set-within-sets" query. Using group by with having is the most generalizable form for such a query. For instance, if you wanted to be sure that category 3 were included, you would change the having clause to:
having max(cat_id = 2) = 0 and
max(cat_id = 7) = 0 and
max(cat_id = 3) = 1
Try something like this :
SELECT DISTINCT item_id
FROM table_category
WHERE item_id NOT IN
( select distinct item_id
from item_category
where cat_id in (2,7)
)
I'd use a nested SELECT, though there are probably ways to do this with a self join.
select item_id
from item_category t
where not exists (
select 1
from item_category
where item_id = t.item_id
and cat_id in (2,7)
)
group by item_id;
Example
You could also use a NOT IN clause instead:
SELECT DISTINCT item_id
FROM item_category
WHERE item_id NOT IN (
select distinct item_id
from item_category
where cat_id in (2,7));
Example
Both queries are probably similar in performance, but you can test if your data set is large.
Something like:
SELECT DISTINCT item_category.item_id
FROM item_category
INNER JOIN (
SELECT item_id ,SUM(CASE cat_id WHEN 2 THEN 1 WHEN 7 THEN 1 ELSE 0 END) AS catcount
FROM item_category
GROUP BY item_id
) AS exclude
ON item_category .item_id = exclude.item_id
WHERE exclude.catcount=0
Updated the answer I think this is what you meant.
One way would be
SELECT DISTINCT ITEM_ID
FROM ITEM_CATEGORY
WHERE ITEM_ID NOT IN (SELECT DISTINCT ITEM_ID
FROM ITEM_CATEGORY
WHERE CATEGORY_ID IN (2, 7))
which produces your desired results. If you want to have a bit more fun, you could do
SELECT DISTINCT ic1.ITEM_ID
FROM ITEM_CATEGORY ic1
LEFT OUTER JOIN (SELECT DISTINCT ITEM_ID
FROM ITEM_CATEGORY
WHERE CATEGORY_ID IN (2, 7)) ic2
ON ic2.ITEM_ID = ic1.ITEM_ID
WHERE ic2.ITEM_ID IS NULL
which also gets the results you're looking for and, if you're not familiar with how a LEFT OUTER JOIN works, might make for an interesting time puzzling through how and why it works.
SqlFiddle here.
Share and enjoy.
It can be done with a simple sub query:
SELECT DISTINCT item_id
FROM ic
WHERE item_id NOT IN (
SELECT DISTINCT item_id FROM ic WHERE cat_id IN (2,7)
);