MySQL - What's the best way to perform this operation - mysql

i've a table like:
| ID | value |
| 0 | 5 |
| 1 | 2 |
| 0 | 1 |
| 1 | 6 |
| 2 | 3 |
| 2 | 8 |
| 1 | 2 |
| 0 | 1 |
| 2 | 4 |
I'm trying to take in my result only one row for id where value is the min of all the column, something like:
SELECT DISTINCT * FROM table WHERE MIN(table.value) = table.value
how can i solve? thanks!
EDIT:
My desired output is:
| ID | value |
| 0 | 1 | -> is the min of all the rows with id = 0
| 1 | 2 |
| 2 | 3 |
EDIT 2:
Something like:
SELECT DISTINCT *
FROM tableName AS A
WHERE value = (SELECT MIN(value) From tableName AS B WHERE A.ID=B.ID)
But tableName is (SELECT * FROM ...........).. how can i perform?

SELECT DISTINCT ID, Value
FROM tableName
WHERE value = (SELECT MIN(value) From tableName)
SQLFiddle Demo
follow-up question, what happens if there are same lowest value with different ID, what record will be shown?

How about this:
SELECT DISTINCT a.ID, a.value
FROM tableName AS a
WHERE a.value = (SELECT MIN(b.value)
FROM tableName AS b
WHERE a.id = b.id)

This is what you want
select id,min(value) from tableName group by id

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)

MySQL Update specified on Count criteria

I have the followin problem:
I want to update all rows where COUNT criteria is greater 1, when not I want to update all except 1. It also should update per other_ID.
Dummytable:
+----+----------+----------+-------------+
| id | other_ID | cirteria | updatefield |
+----+----------+----------+-------------+
| 1 | 1 | 1 | 0 |
| 2 | 1 | 1 | 0 |
| 3 | 1 | 1234 | 0 |
| 4 | 2 | 2 | 0 |
| 5 | 2 | 1 | 0 |
| 6 | 2 | 1 | 0 |
| 7 | 4 | 20 | 0 |
| 8 | 4 | 1 | 0 |
| 9 | 4 | 60 | 0 |
| 10 | 5 | 1 | 0 |
| 11 | 5 | 1 | 0 |
| 12 | 6 | 5 | 0 |
+----+----------+----------+-------------+
excpected result:
+----+----------+----------+-------------+
| id | other_ID | cirteria | updatefield |
+----+----------+----------+-------------+
| 1 | 1 | 1 | 1 |
| 2 | 1 | 1 | 1 |
| 3 | 1 | 1234 | 0 |
| 4 | 2 | 2 | 0 |
| 5 | 2 | 1 | 1 |
| 6 | 2 | 1 | 1 |
| 7 | 4 | 20 | 0 |
| 8 | 4 | 1 | 1 |
| 9 | 4 | 60 | 0 |
| 10 | 5 | 1 | 0 |
| 11 | 5 | 1 | 1 |
| 12 | 6 | 5 | 0 |
+----+----------+----------+-------------+
my idea:
UPDATE pics AS tu SET updatefield=1 WHERE criteria=1 AND (select count(*) as cnt2 from pics where criteria>1 group by other_id)>1;
Error: Table 'tu' is specified twice, both as a target for 'UPDATE' and as a separate source for data
Also I have problems to geht the right count:
SELECT other_id, count() as cnt FROM pics AS ts WHERE criteria=1 and (select count() as cnt2 from pics where criteria>1)>0 GROUP BY other_id;
i want to get cnt = 1 for other_id=5, but i get cnt=2
with
SELECT other_id, COUNT(*) AS cnt2
FROM pics
WHERE criteria>1
GROUP BY other_id;
I get all other_ids where i want to update the updatefield. But how can I connect it with the update? And how to get all except one for other_id=5
You can alias the sub query into another query, e.g.:
UPDATE test
SET updatefield = 1
WHERE updatefield = 0 AND criteria = 1
AND other_id IN (
SELECT a.id FROM (
SELECT other_id AS id
FROM test
WHERE criteria > 1
GROUP BY other_id
HAVING COUNT(*) > 1
) a
);
Here's the SQL Fiddle.
Update
This will update the ids for records with criteria 0 and >1. Now, to update the records where there is more than one record with 1 criteria, you need to do something like this:
UPDATE test
SET updatefield = 1
WHERE updatefield = 0 AND criteria = 1
AND id IN (
SELECT a.id FROM (
SELECT MIN(id) AS id
FROM test
WHERE criteria = 1
GROUP BY other_id
HAVING COUNT(*) > 1
) a
);
Thanks to #Darshan Mehtas answer and help I finally found the solution to solve it as I want.
Here's the complete solution:
UPDATE test
SET updatefield = 1
WHERE updatefield = 0 AND criteria = 1
AND id not IN (
SELECT a.id FROM (
SELECT id
FROM test
WHERE criteria>1
) a
)
AND id not IN (
SELECT b.id FROM (
SELECT id
FROM test
GROUP BY other_id
HAVING COUNT(*) = 1
) b
)
AND id NOT IN (
SELECT c.id FROM (
SELECT id
FROM test
WHERE criteria=1 AND other_id NOT IN (
SELECT other_id FROM test WHERE Criteria>1
)
GROUP BY other_id, criteria
HAVING COUNT(criteria)>1
) c
);
Short description:
First Subquery (a) filters IDs where a criteria is greater 1
Second Subquery (b) filters IDs which have only on result
Third Subquery (c) filters IDs Where criteria is 1an don't have any higher criteria and keeps, thansk grouping, the first result.
Only bad thing could be to keep in the last subquery (c) the first (mostly oldest) result instead of newest.
€dit:
to keep the last result use this for subquery c instead:
AND id NOT IN (
SELECT c.id FROM (
SELECT id
FROM test t1
JOIN (SELECT other_id, max(id) maxid
FROM test
GROUP BY other_id) t2
ON t1.otheR_id=t2.other_id AND t1.id=t2.maxid
WHERE criteria=1 AND t1.other_id NOT IN (
SELECT other_id FROM test WHERE Criteria>1
)
GROUP BY t1.other_id, criteria
) c
);

MySQL Multiple Row Compare

I'm trying to run a query that will compare multiple rows in the same table and shows me all results that match.
For example, my data will look like this:
+-------------+-----------+---------+------------+-------+
| activity_id | d_id | tech_id | timestamp | value |
+-------------+-----------+---------+------------+-------+
| 39248078 | 1 | 1 | 2014-03-09 | 1 |
| 39248079 | 2 | 1 | 2014-03-06 | 1 |
| 39248082 | 3 | 1 | 2014-04-09 | 0 |
| 39248085 | 1 | 2 | 2014-03-13 | 1 |
| 39248088 | 3 | 2 | 2014-07-17 | 1 |
| 39248091 | 1 | 3 | 2014-02-07 | 1 |
| 39248093 | 2 | 3 | 2014-12-02 | 0 |
+-------------+-----------+---------+------------+-------+
The goal is to get all d_ids where tech_id = 3 AND (tech_id = 1 OR tech_id = 2). So in this case, the result should be 1 and 2 but not 3.
I've looked into subqueries but wasn't able to get it to work. Any help would be much appreciated.
SELECT
d_id
FROM table
WHERE d_id IN(
SELECT
d_id
FROM table
WHERE tech_id=3
) AND tech_id=1 OR tech_id=2
Let me know if it didn't work!
maybe something like this?
I havent tested it but from what I understand something like this should work
SELECT * FROM (
SELECT activity_id, d_id, tech_id, timestamp, value FROM test
WHERE tech_id = 3
) as temp
JOIN test t on t.d_id = temp.d_id
WHERE t.tech_id = 1 OR t.tech_id = 2
with CTE as
(
select * from table
where tech_id = 3
)
select c.d_id
from CTE c
where tech_id = 2 or tech_id = 3
Edited:
with CTE as
(
select * from table
where tech_id = 3
)
select c.d_id
from CTE c
where tech_id = 2 or tech_id = 3

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)