SQL query to only yield multiple occurances - mysql

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;

Related

SQL get rows based on two ids

I really don't know how to title this problem properly.
Heres the table structure:
ID | CLIENT_ID | …
ID is primary and auto increment. CLIENT_ID on the other hand can occur multiple times.
What i want is to fetch the rows by CLIENT_ID with highest ID ... Heres a example
ID | CLIENT_ID
1 | 1
2 | 1
3 | 2
4 | 3
5 | 2
So here CLIENT_ID 1 and 2 occurs multiple times (because there is a newer version).
After the query i want the following IDs in the results: 2,4,5 (Because the highest ID in rows with CLIENT_ID 1 is the row with ID 2 and so on)
If you need all the columns you can use a select in
select * from my_table
where (id, client_id) in ( select max(id), client_id
from my_table
group by client_id);
but if you need only the id
select id from my_table
where (id, client_id) in ( select max(id), client_id
from my_table
group by client_id);
or more simple
select max(id)
from my_table
group by client_id;
SELECT * FROM table GROUP BY client_id HAVING max(id)
this should be more efficient than a sub select

MySQL - remove non-duplicate rows from query

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

Multiple Aggregate with different Group By

I have table User, Company, ParentCompany and table Goal.
Each Company have ParentCompany, and each User inside one Company. Goal have number of action, and type of Goal, user who execute the goal, and time executed.
I want to calculate the number of action in a date range for each type of Goal, for each user, company, and parent_company. Number of action for each company equal to sum of action for user that reside in that company.
More or less after some join query, I able to get this table below, where column id is id of company, parent_id is id of companyparent, and num is number of goal for all user inside of id company.
id parent_id num
----------- -------------------- -----------------------
1 3 1
2 1 2
3 1 1
4 2 4
Now I want to make it like below:
id parent_id sum_id sum_parent
----------- -------------------- -------------- -------------
1 3 1 1
2 1 2 3
3 1 1 3
4 2 4 4
How can I make it works? I can get one of the value (sum_id or sum_parent) with GROUP BY,
SELECT id,SUM(num) AS sum_id FROM tableA GROUP BY id
or
SELECT parent_id,SUM(num) AS sum_parent FROM tableA GROUP BY parent_id
but is there any way to make it only in one query? tableA results from query with 5 join inside.
Try this:
SELECT a.id, a.parent_id, a.sum_id, b.sum_parent
FROM (SELECT id, parent_id, SUM(num) sum_id FROM tableA a GROUP BY id) a
INNER JOIN (SELECT parent_id, SUM(num) sum_parent FROM tableA a GROUP BY parent_id) b ON a.parent_id = b.parent_id
Try this :
SELECT
t1.id, t1.parent_id, t1.sum_id, t2.sum_parent
FROM
(SELECT id, parent_id, SUM(num) AS sum_id FROM mytable GROUP BY id) t1
INNER JOIN
(SELECT parent_id, SUM(num) AS sum_parent FROM mytable GROUP BY parent_id) t2
ON t1.parent_id = t2.parent_id
Apparently what I want can be done with WITH ROLLUP statement. (http://dev.mysql.com/doc/refman/5.0/en/group-by-modifiers.html)
With
SELECT id,sum(num) FROM tableA GROUP BY parent_id, id WITH ROLLUP;
will results in
parent_id id sum(num)
----------- -------------------- --------------
1 2 2
1 3 1
1 null 3
2 4 4
2 null 4
3 1 2
3 null 2

MySQL: Select Order Only if all its Items are ready status

I will simplify the table like this:
table order:
order_id | name
1 a
2 b
3 c
Table order_item:
item_id | fk_order_id | status
1 1 0
2 1 1
3 2 1
4 2 1
5 3 0
Ready status let say is 1, so only order_id=2 has all its items are on ready status.
How can I query select it?
There are a couple ways of doing this -- here is one using COUNT -- gets COUNT of all and compares to COUNT of Status = 1:
SELECT fk_order_id
FROM (
SELECT fk_order_id,
COUNT(1) totCount,
COUNT(CASE WHEN Status = 1 THEN 1 END) statusCount
FROM Order_Item
GROUP BY fk_order_id
) t
WHERE totCount = statusCount
SQL Fiddle Demo
This could be consolidated into a single query, but I think it reads better using a subquery.
Try this:
SELECT order_id ,name FROM order,order_item
WHERE order.order_id =order_item.fk_order_id
group by order_id ,name having min(status)=1

MYSQL SUM() in one table and JOIN with 2 other tables

I have 3 tables: items, purchases, and collaborators. A user can own an item, purchase an item, or be a collaborator on an item. Additionally, items that are purchased can be rated up, +1, or down, -1. An owner or collaborator can't purchase their own item.
I'd like to get all items for a given user and also display the ratings on each item.
Here's my tables:
items | purchases | collaborators
i_id item_id user_id | p_id item_id user_id rating |c_id item_id user_id
1 1 11 | 1 1 13 -1 | 1 1 12
2 2 12 | 2 2 11 1 | 2 2 13
3 3 13 | 3 3 12 NULL |
| 4 1 14 -1 |
Here's my MYSQL query so far:
select *, count(p_id) as tots, sum(rating=1) as yes, sum(rating= '-1') as no
from items
left join purchases
on items.item_id=purchases.item_id
left join collaborators
on items.item_id=collaborators.item_id
where items.user_id=13 or purchases.user_id=13 or collaborators.user_id=13
group by items.item_id
Here's my expected results for user_id=11 (changing each user_id in the WHERE clause):
item_id tots yes no
1 2 0 2
2 1 1 0
// notice how user_id=11 doesn't have anything to do with item_id=3
Here's my expected results for user_id=12:
item_id tots yes no
1 2 0 2
2 1 1 0
3 1 1 0
Here's my expected results for user_id=13:
item_id tots yes no
1 2 0 2
2 1 1 0
3 1 1 0
//notice user_id=13 should have same results as user_id=12. Although, their
relation to each of the 3 items is different, they still either purchased,
own, or collaboratored on each of them.
Unfortunately, I get the first two results but not the correct one for user_id=13.
For user_id=13, item_id=1 the tots=1 and not tots=2 for some reason I can't understand.
Any thoughts, such as, "its better to separate this into 2 queries", would be greatly appreciated,
I'm still not entirly sure I understand you correct but you could try following statement and let us work from there.
Edit
Following statement returns the expected results.
You can verify this (using SQL Server) here.
The gist of this is to
select all possible user_id and item_id combinations from your three tables
select the counts/ratings for each item
combine the results
SQL Statement
SELECT u.user_id, pt.item_id, pt.cnt, pt.yes, pt.no
FROM (
SELECT user_id, item_id, title FROM items
UNION SELECT user_id, item_id, NULL FROM purchases
UNION SELECT user_id, item_id, NULL FROM collaborators
) u INNER JOIN (
SELECT COUNT(*) AS cnt
, SUM(CASE WHEN ISNULL(rating, 1) = 1 THEN 1 ELSE 0 END) AS yes
, SUM(CASE WHEN rating =-1 THEN 1 ELSE 0 END) AS no
, item_id
FROM purchases
GROUP BY
item_id
) pt ON pt.item_id = u.item_id
MYSQL statement
SELECT u.user_id, pt.item_id, pt.cnt, pt.yes, pt.no, u.title
FROM (
SELECT user_id, item_id, title FROM items where user_id=13
UNION SELECT user_id, item_id, NULL FROM purchases where user_id=13
UNION SELECT user_id, item_id, NULL FROM collaborators where user_id=13
) u INNER JOIN (
SELECT COUNT(*) AS cnt
, SUM(rating=1) AS yes
, SUM(rating =-1) AS no
, item_id
FROM purchases
GROUP BY
item_id
) pt ON pt.item_id = u.item_id