SQL query to group data - mysql

There is a requirement that I need to fill a group-id in a table as combination of item-id and auto-id. The table is as follows;
----------------------------------------
Item_id | Auto_id | Group_id
----------------------------------------
1 | 1 | 1
1 | 2 | 1
2 | 3 | 3
2 | 4 | 3
3 | 5 | 5
3 | 6 | 5
3 | 7 | 5
4 | 8 | 8
4 | 9 | 8
5 | 10 | 10
6 | 11 | 11
The two columns would be populated already that is Item_id and Auto_id, and we need to fill group_id. The relation would be like for each repetitive item_id the group_id would be minimum of auto_id.
I hope I make it clear. If possible please help.
Thanks,
Ashish

You can use a subquery, with a group by, where you calculate the minimum auto_id for each item_id. Then you can join this subquery with the original table:
SELECT t1.Item_id, t1.Auto_id, t2.Group_id
FROM
yourtable t1 INNER JOIN (
SELECT Item_Id, MIN(Auto_id) Group_id
FROM yourtable
GROUP BY Item_Id) t2
ON t1.Item_Id=t2.ItemId
Please see fiddle here.
If you need to update an existing column, you could use this UPDATE query:
UPDATE
yourtable t1 INNER JOIN (
SELECT Item_Id, MIN(Auto_id) Group_id
FROM yourtable
GROUP BY Item_id) t2
ON t1.Item_Id=t2.Item_Id
SET
t1.Group_id=t2.Group_id
Fiddle is here.

Related

How to select rows, using group by with minimum field values?

Today I have posted a question and got a good answer: Stuck in building mysql query.
I though it helped me, but I've discovered that it returns wrong data. So I'm reposting the question here, with an answer I received, as well I will explain the problem why it is not working for me.
Example of data:
id | item_id | user_id | bid_price
----------------------------------
1 | 1 | 11 | 1
2 | 1 | 12 | 2
3 | 1 | 13 | 3
4 | 1 | 14 | 1
5 | 1 | 15 | 4
6 | 2 | 16 | 2
7 | 2 | 17 | 1
8 | 3 | 18 | 2
9 | 3 | 19 | 3
10 | 3 | 18 | 2
Expected result:
id | item_id | user_id | bid_price
----------------------------------
1 | 1 | 11 | 1
7 | 2 | 17 | 1
8 | 3 | 18 | 2
Offered solution:
select m.id, m.item_id, m.user_id, m.bid_price
from my_table m
inner join (
select item_id, min(id) min_id, min(bid_price) min_price
from my_table
where item_id IN (1,2,3)
group by item_id
) t on t.item_id = m.item_id
and t.min_price= m.bid_price
and t.min_id = m.id
The problem:
In the sub query the minimum ID is selected entire the group by (item_id) statement and doesn't reflects according to minimum bid_price.
In other words, the minimum id is selected not depending on the price field at all. So, in the result I will get minimum price and minimum id of the group, but this will not be the same row! The id can be related to the row with another bet_price value.
How this query can be adjusted? Thank you in advance!
SELECT min(m.id) AS id, m.item_id, m.user_id, m.bid_price
FROM my_table m
INNER JOIN (
SELECT item_id, min(bid_price) AS min_price
FROM my_table
GROUP BY item_id
) t ON t.item_id = m.item_id
AND t.min_price= m.bid_price
GROUP BY item_id
Output
id item_id user_id bid_price
1 1 11 1
7 2 17 1
8 3 18 2
Live Demo
http://sqlfiddle.com/#!9/a52dc6/13
SELECT DISTINCT
t1.item_id,
t1.bid_price
FROM tab1 t1
WHERE NOT exists(SELECT 1
FROM tab1 t2
WHERE t2.item_id = t1.item_id
AND t2.bid_price < t1.bid_price)
AND t1.item_id IN (1, 2, 3);
http://sqlfiddle.com/#!9/615e0a/5

How to make cross select in one table?

Consider this table:
I need to make a SQL query which returns highlighted rows. In other words: rows which are linked to each other by idContactTo.
Example:
1 has contact to 2, 2 has contact to 1 - they are linked and should be in result table. But even 1 has contact to 3 it doesn't mean that 3 has contact to 1 - they aren't linked.
You can do it via INNER JOIN,
SELECT a.*
FROM tableName a
INNER JOIN tableName b
ON a.idContantOwner = b.idContactTo AND
b.idContantOwner = a.idContactTo
SQLFiddle Demo
Another way to do it
SELECT t.*
FROM
(
SELECT MiN(id) min_id, MAX(id) max_id
FROM Table1
GROUP BY LEAST(idContactOwner, idContactTo),
GREATEST(idContactOwner, idContactTo)
HAVING COUNT(*) = 2
) q JOIN Table1 t
ON t.id IN(q.min_id, q.max_id)
Output:
| ID | IDCONTACTOWNER | IDCONTACTTO |
|----|----------------|-------------|
| 1 | 1 | 2 |
| 2 | 2 | 1 |
| 4 | 3 | 4 |
| 5 | 4 | 3 |
Here is SQLFiddle demo

Mysql query sum values into multiple rows

I have this
id value
-----!-----
1 3
2 3
1 2
1 1
i have tried using
SELECT id,sum(value) FROM table GROUP BY id
but it shows something different.
id ! value
--------------
1 6
2 3
And i want to add values based on their id's but keeping id's there
id ! value
--------------
1 6
2 3
1 6
1 6
Please help
Thank you
Are you looking for this?
SELECT t.id, q.value
FROM Table1 t JOIN
(
SELECT id, SUM(value) value
FROM Table1
GROUP BY id
) q ON t.id = q.id
Output:
| ID | VALUE |
|----|-------|
| 1 | 6 |
| 2 | 3 |
| 1 | 6 |
| 1 | 6 |
Here is SQLFiddle demo
The naive approach would be :
select id, (select sum(value) from tbl where id = t1.id) value
from tbl t1

how to find duplicates and gaps in this scenario in mysql

Hi I have a table that looks like
-----------------------------------------------------------
| id | group_id | source_id | target_id | sortsequence |
-----------------------------------------------------------
| 2 | 1 | 2 | 4 | 1 |
-----------------------------------------------------------
| 4 | 1 | 20 | 2 | 1 |
-----------------------------------------------------------
| 5 | 1 | 2 | 14 | 1 |
-----------------------------------------------------------
| 7 | 1 | 2 | 7 | 3 |
-----------------------------------------------------------
| 20 | 2 | 20 | 4 | 3 |
-----------------------------------------------------------
| 21 | 2 | 20 | 4 | 1 |
-----------------------------------------------------------
Scenario
There are two scenarios that needs to be handled.
Sortsequence column value should be unique against one source_id and group_id. For example if all the records having group_id = 1 AND source_id = 2 should have sortsequence unique. In above example records having id= and 5 which are having group_id = 1 and source_id = 2 have same sortsequence which is 1. This is faulty record. I need to find out these records.
If group_id and source_id is same. The sortsequence columns value should be continous. There should be no gap. For example in above table records having id = 20, 21 having same group_id and source_id and sortsequence value is 3 and 1. Even this is unique but there is a gap in sortsequence value. I need to also find out these records.
MY So Far Effort
I have written a query
SELECT source_id,`group_id`,GROUP_CONCAT(id) AS children
FROM
table
GROUP BY source_id,
sortsequence,
`group_id`
HAVING COUNT(*) > 1
This query only address the scenario 1. How to handle scenario 2? Is there any way to do it in same query or I have to write other to handle second scenario.
By the way query will be dealing with million of records in table so performance must be very good.
Got answer from Tere J Comments. Following query covers above mentioned both criteria.
SELECT
source_id, `group_id`, GROUP_CONCAT(id) AS faultyIDS
FROM
table
GROUP BY
source_id,group_id
HAVING
COUNT(DISTINCT sortsequence) <> COUNT(sortsequence) OR COUNT(sortsequence) <> MAX(sortsequence) OR MIN(sortsequence) <> 1
May be it can help others.
Try this query it will solve both of the cases as you have mentioned in the question.
SELECT
a.*
FROM
tbl a
INNER JOIN
(select
#rn:=IF(#prevG = group_id AND #prevS = source_id, #rn + 1, 1) As rId,
#prevG:=group_id AS group_id,
#prevS:=source_id AS source_id,
id,
sortsequence
FROM
tbl
join
(select #rn:=0, #prevS:=0, #prevG:=0)b
order by group_id, source_id, id) b
ON a.id = b.id AND a.SORTSEQUENCE <> b.RID;
FIDDLE

INNER JOIN DISTINCT with MySQL

I have a mysql problem. I have two tables like this that I need to join together.
table:
id otherid2
1 | 1
2 | 1
3 | 2
4 | 2
table2:
otherid otherid2
1 | 1
2 | 1
3 | 2
4 | 2
I'm using:
SELECT id,otherid FROM table INNER JOIN table2 ON table.otherid2=table2.otherid2
This gives me:
id otherid
1 | 1
1 | 2
2 | 1
2 | 2
3 | 3
3 | 4
4 | 3
4 | 4
As you can see I get duplicates of id as there is otherid2s that is not unique in table2. What I need is to INNER JOIN DISTINCT in some way, I only want the result to be as below. Not duplicates.
This is what I want:
id otherid
1 | 1
2 | 1
3 | 3
4 | 3
Can I do this in an easy way?
If you want the row with the lowest id in table2, this should probably do it
SELECT id, min(otherid)
FROM table
INNER JOIN table2
ON table.otherid2=table2.otherid2
GROUP BY id
In your comment you wanted the lowest, then I'd suggest a group by and a min aggregator
SELECT id, MIN(otherid) AS otherid ... GROUP BY id