Group by two column with min condition - mysql

I have next table:
| ID |ID2 | price|
+----+---+----+
| A | AA | 7 |
| B | AA | 3 |
| C | AA | 4 |
| D | BB | 7 |
| I | BB | 2 |
| F | BB | 3 |
| G | CC | 9 |
| E | CC | 4 |
| K | CC | 1 |
+----+---+---+
And I need to get the next table
group by ID2 with min field price and corresponding min price field ID1
| ID1 | ID2 | min_price |
+----+---+---+----------
| B | AA | 3 |
| I | BB | 2 |
| K | CC | 1 |
+----+---+---+---------

select a.id, a.id2, a.price from #yourtable a
join
(
select id2, min(price) AS price
from #yourtable
group by id2
)b
on a.id2=b.id2 and a.price=b.price

SELECT *
FROM
#table t
INNER JOIN (
SELECT
ID2
,MIN(price) as min_price
FROM
#table
GROUP BY
ID2
) g
ON t.ID2 = g.ID2
AND t.price = g.min_price
Step 1 find the minimum price, step 2 relate back to get the original record that matches to get the ID. There are other ways to do this as well.
Note that if your dataset contains 2 records in the same ID2 with the same price then more than 1 record will always be returned.

Based on your explanation, we need to group by id2 and get the lowest price and its corresponding id.
Here is the query for the same
SELECT id,
id2,
price
FROM NEXT
WHERE (price,id2) IN
(SELECT MIN(price), id2 FROM NEXT GROUP BY id2
);

http://sqlfiddle.com/#!9/295702/2
SELECT t1.*
FROM t1
LEFT JOIN t1 t2
ON t1.id2=t2.id2
AND t1.price>t2.price
WHERE t2.ID IS NULL

Related

MySQL find duplicates based on another column value

I have the following table
+----+------+-------+
| id | user | value |
+----+------+-------+
| 1 | 10 | A |
| 2 | 12 | B |
| 3 | 24 | A |
| 4 | 33 | C |
+----+------+-------+
I want to retreive all the duplicates users that have the same key
+----+------+-------+
| id | user | value |
+----+------+-------+
| 1 | 10 | A |
| 3 | 24 | A |
+----+------+-------+
I've tried that with no luck
SELECT DISTINCT A.user, A.value
FROM table as A
INNER JOIN ( SELECT value FROM table GROUP BY value HAVING COUNT(value) > 1 ) AS B
ON A.value = B.value
You may try below query -
SELECT id, user, value
FROM YUOR_TABLE T1
WHERE EXISTS (SELECT 1
FROM YOUR_TABLE T2
WHERE T1.value = T2.value
AND T1.user <> T2.user)

SQL query to get minimal sum value and associated column from table

I have following tables:
t1 - Items
| Id | Item |
| 1 | I1 |
| 2 | I2 |
t2 - Item_elements
| Id | Item_id | Element | Our_quantity | Client_quantity |
| 1 | 1 | E11 | 100 | 0 |
| 2 | 1 | E12 | 20 | 300 |
| 3 | 2 | E21 | 300 | 100 |
| 4 | 2 | E22 | 5 | 300 |
t3 - Element_operations
| Id | Element_id | Operations_number |
| 1 | 1 | 100 |
| 2 | 1 | 50 |
| 3 | 2 | 50 |
| 4 | 2 | 50 |
| 5 | 3 | 50 |
| 6 | 3 | 50 |
| 7 | 3 | 50 |
| 8 | 3 | 50 |
| 9 | 4 | 10 |
I need SQL query which return table witch items (t1) AND element row associated with item table which has minimum operations number
Desired Output:
Table should look like
| Id|Item| Id_el |Our_quantity| Client_quantity | Count Operations_number|
| 1| I1 | 2 | 20 | 300 | 100 |
| 2| I2 | 4 | 5 | 300 | 10 |
result
I tried that query
SELECT t2.Id,Item_id,Our_Quantity,Client_Quantity,SUM(Operations_number)
FROM t2 LEFT JOIN t3 ON t2.Id=t3.Id_el GROUP BY t2.Id)
Tried Result:
| Id | Item_id | Our_quantity | Client_quantity |SUM(Operations_number)
| 1 | 1 | 100 | 0 | 150
| 2 | 1 | 20 | 300 | 100
| 3 | 2 | 300 | 100 | 200
| 4 | 2 | 5 | 300 | 10
What should I do next?
Now I have 2 table:
| Element Id | Item_id |Sum operations_number for element |
| 1 | 1 | 150 |
| 2 | 1 | 100 |
| 3 | 2 | 200 |
| 4 | 2 | 10 |
| Item Id | Item |
| 1 | I1 |
| 2 | I2 |
How can I join them to get this table?
Item Element who has minimal sum operations number.
| Item Id | Item | Element_Id | Sum operations_number for element |
| 1 | I1 | 2 | 100 |
| 2 | I2 | 4 | 10 |
You could get desired output using this..
SELECT
t.*,
MIN(t.opsum) AS `Count Operations_number`
FROM
(SELECT
a.*,
b.Id AS `Id_el`,
b.`Our_quantity`,
b.`Client_quantity`,
SUM(c.`Operations_number`) AS opsum
FROM
`t1` AS a
LEFT JOIN `t2` AS b
ON a.`Id` = b.`Item_id`
LEFT JOIN `t3` AS c
ON b.`Id` = c.`Element_id`
GROUP BY a.Id,
b.Id
ORDER BY a.`Id` ASC,
opsum ASC) AS t
GROUP BY t.Id ;
FIDDLE HERE
Maybe if you use the MIN() method in the desired column, as example:
SQL
SELECT t2.Id,Item_id, MIN(Our_Quantity), Client_Quantity, SUM(Operations_number)
FROM t2 LEFT JOIN t3
ON t2.Id=t3.Id_el
GROUP BY t2.Id
You may try this..
For mysql 8+
with cte as (
SELECT t1.id as Item_id, t1.item, t2.id as Ele_Id, t2.Element , t2.Our_quantity , t2.Client_quantity , t3.Operations_number
from Items as t1
inner join Item_elements as t2 on t1.id=t2.Item_id
inner join Item_elements as t3 on t2.id = t3.Element_id
)
, ct as (
select row_number() over ( partition by t1.id order by t2.Our_quantity ) as Slno, * from cte
)
select c.item_id, c.item, c.Ele_id, c.Element, c.our_quantity, c.client_quantity, t.Count_Operations_number
from ct as c
inner join
(
select distinct Element_id , sum(Operation_number) as Count_Operations_number
from Element_operations group by Element_id
) as t
on c.Ele_id=t.Element_id
where c.slno=1
Try the below query, hope this is what you are asking
select t1.Id as 'Id',t1.Item as 'Item',
t.Id as 'Id_el', t.Our_quantity as 'Our_quantity',t.Client_quantity as 'Client_quantity',
sum(t3.Operations_number) as 'Count Operations_number'
from t1 join (select *
from t2 where (Item_id,Our_quantity) in
( select Item_id, min(Our_quantity) from t2 group by Item_id)) t on t1.Id=t.Item_id
join t3 on t.Id=t3.Element_id
group by t1.Id;
Do you want it in the minimum order of SUM(Operations_number)?
Try this
I have updated the answer so this will get the first table also.
SELECT t1.id,
t1.item,
id_el,
our_quantity,
client_quantity,
sum
FROM t1
JOIN (SELECT t2.id AS Id_el,
t2.item_id,
t2.our_quantity AS our_quantity,
t2.client_quantity AS client_quantity,
sum
FROM t2
JOIN (SELECT t3.element_id,
Sum(operations_number) AS sum
FROM t3
GROUP BY element_id) AS b
ON t2.id = b.element_id) AS c
ON t1.id = c.item_id
ORDER BY sum ASC
Output would be:

SQL - How can I JOIN two tables and SUM a column based on IDs between them?

I have two tables. One table is with master data
Table tbl1:
+-------------+------------+------------+
| ID | Name | Total |
+-------------+------------+------------+
| 1 | a | 10 |
| 2 | b | 5 |
| 3 | c | 4 |
| 4 | a | 4 |
+-------------+------------+------------+
Second table tbl2 contains child data. The key between tables is ID
Table tbl2:
+-------------+------------+
|id | qty |
+-------------+------------+
| 1 | 4 |
| 1 | 3 |
| 1 | 1 |
| 3 | 1 |
| 3 | 3 |
+-------------+------------+
I need to get output like this:
Output:
+-------------+------------+------------+
| name | sum_tot | sum_qty |
+-------------+------------+------------+
| a | 14 | 8 |
| b | 5 | 0 |
| c | 4 | 4 |
+-------------+------------+------------+
I had tried with this:
select tbl1.name, SUM(tbl1.total), SUM(tbl2.qty)
from tbl1
left join tbl2 ON tbl1.id = tbl2.id
GROUP by tbl1.name
The output that I get is:
Output:
+-------------+------------+------------+
| name | sum_tot | sum_qty |
+-------------+------------+------------+
| a | 34 | 8 |
| b | 5 |null |
| c | 8 | 4 |
+-------------+------------+------------+
Which is not correct.
Here is the sql fiddle:
The summary from first table is not in relation with second table. It seems that somehow query runs three times.
You can simply have a correlated sub-query that calculates the tbl2 sum:
select tbl1.name,
SUM(tbl1.total),
SUM(COALESCE((select SUM(tbl2.qty)
from tbl2
where tbl1.id = tbl2.id), 0)) as qty_tot
from tbl1
GROUP by tbl1.name
SELECT A.name, SUM(A.total) as sum_tot, COALESCE(B.sum_qty, 0) as sum_qty
FROM tbl1 A
LEFT JOIN (
SELECT id, SUM(qty) as sum_qty
FROM tbl2
GROUP BY id
) B ON B.id = A.id
GROUP BY A.name
select tbl1.name, SUM(tbl1.total), SUM(COALESCE(tbl2.qty, 0))
from tbl1
left join tbl2 ON tbl1.id = tbl2.id
GROUP by tbl1.name

Find the maximum value(s) from a column and selecting their rows

After looking at other examples I still have not been able to find a solution, that is why I am asking for some help.
My table structure:
V_id | name | group_id | other columns
----------------------
1 | | 1
2 | | 1
3 | | 2
4 | | 3
5 | | 3
I have been struggling to build a query, to select all the rows which have the maximum value from the group_id column.
therefore output should be like this:
V_id | name | group_id | other columns
----------------------
4 | | 3
5 | | 3
which I believe can be solved by selecting all records where group_id is the highest.
and also need a query to get all the other remaining rows.
which in this case, should be like this:
V_id | name | group_id | other columns
----------------------
1 | | 1
2 | | 1
3 | | 2
which I believe can be done by selecting all records where group_id < Max(group_id)
for the first part of the problem,
SELECT *
FROM tableName
WHERE group_id = (SELECT MAX(group_ID) FROM TableName)
and for the second part,
SELECT *
FROM tableName
WHERE group_id < (SELECT MAX(group_ID) FROM TableName)
You can use JOIN for that:
SELECT a.*
FROM Table1 a
JOIN (SELECT MAX(Group_ID) AS MAXID
FROM Table1) B
ON a.Group_id = B.MaxID;
Result:
| V_ID | NAME | GROUP_ID |
----------------------------
| 4 | (null) | 3 |
| 5 | (null) | 3 |
For the remaining rows use LEFT JOIN with a condition like this:
SELECT a.*
FROM Table1 a
LEFT JOIN (SELECT MAX(Group_ID) AS MAXID
FROM Table1) B
ON a.Group_id = B.MaxID
WHERE B.MaxID IS NULL;
Result:
| V_ID | NAME | GROUP_ID |
----------------------------
| 1 | (null) | 1 |
| 2 | (null) | 1 |
| 3 | (null) | 2 |
See this SQLFiddle

MySQL SELECT value before MAX

How to select 1st, 2nd or 3rd value before MAX ?
usually we do it with order by and limit
SELECT * FROM table1
ORDER BY field1 DESC
LIMIT 2,1
but with my current query I don't know how to make it...
Sample table
+----+------+------+-------+
| id | name | type | count |
+----+------+------+-------+
| 1 | a | 1 | 2 |
| 2 | ab | 1 | 3 |
| 3 | abc | 1 | 1 |
| 4 | b | 2 | 7 |
| 5 | ba | 2 | 1 |
| 6 | cab | 3 | 9 |
+----+------+------+-------+
I'm taking name for each type with max count with this query
SELECT
`table1b`.`name`
FROM
(SELECT
`table1a`.`type`, MAX(`table1a`.`count`) AS `Count`
FROM
`table1` AS `table1a`
GROUP BY `table1a`.`type`) AS `table1a`
INNER JOIN
`table1` AS `table1b` ON (`table1b`.`type` = `table1a`.`type` AND `table1b`.`count` = `table1a`.`Count`)
and I want one more column additional to name with value before max(count)
so result should be
+------+------------+
| name | before_max |
+------+------------+
| ab | 2 |
| b | 1 |
| cab | NULL |
+------+------------+
Please ask if something isn't clear ;)
AS per your given table(test) structure, the query has to be as follows :
select max_name.name,before_max.count
from
(SELECT type,max(count) as max
FROM `test`
group by type) as type_max
join
(select type,name,count
from test
) as max_name on (type_max.type = max_name.type and count = type_max.max )
left join
(select type,count
from test as t1
where count != (select max(count) from test as t2 where t1.type = t2.type)
group by type
order by count desc) as before_max on(type_max.type = before_max .type)