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
Related
With the query:
SELECT TableA.ID, TableA.SensorID, TableA.Value, SensorIDs.Name, TableA.timestamp
FROM TableA
JOIN SensorIDs
ON TableA.SensorID = SensorIDs.ID // column 'Name' is in 'SensorIDs'
My result table looks like this:
ID | SensorID | Value | Name | timestamp
1 | 1 | 5 | A | 1000
2 | 2 | 10 | B | 1000
3 | 3 | 0 | C | 1000
4 | 1 | 1 | A | 2000
5 | 2 | 2 | B | 2000
6 | 3 | 6 | C | 2000
[..]
Is there a way to change my SQL query to get a table like this:
A | B | C | timestamp
5 | 10 | 0 | 1000
1 | 2 | 6 | 2000
Something with GROUP BY maybe?
EDIT: In the forseeable future there will be only these 3 values for 'Name'.
EDIT: RDBMS: MySQL-native (InnoDB), PHPMyAdmin
EDIT: Forgot to add column "SensorID" in the result.
I found the answer, by creating a PIVOT table with the tutorial I found here:
https://ubiq.co/database-blog/how-to-create-pivot-table-in-mysql/
SELECT time,
sum(IF(SensorID=1, Value, NULL)) AS Sensor1,
sum(IF(SensorID=2, Value, NULL)) AS Sensor2,
sum(IF(SensorID=3, Value, NULL)) AS Sensor3,
sum(IF(SensorID=4, Value, NULL)) AS Sensor4
FROM TableA
GROUP BY time
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
);
I have data something like this:
| visitor_id | time | my_flag |
| 1 | 01-01-2017 | 1 |
| 2 | 01-01-2017 | 1 |
| 1 | 01-02-2017 | 2 |
| 3 | 01-02-2017 | 2 |
etc...
I want to group all visitors in one day but based on a flag. The flag can have two values, 1 or 2. So I need something like
| 12 | 01-01-2017 | 1 |
| 10 | 01-01-2017 | 2 |
| 34 | 01-02-2017 | 1 |
I have
select v.visitor_id v.time, v.flag
from my_table as v
group by DAY(v.time) having flag=1;
But I am not able to figure out how to add multiple conditions (flag=1 and flag=2)? Any pointers?
try something like this
select v.visitor_id v.time, v.flag
from my_table as v
where v.flag in (1,2)
group by DAY(v.time), v.flag
SELECT v.time,
v.flag,
COUNT(v.visitor_id)
FROM my_table as v
GROUP BY v.time,
v.flag;`
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
I have table like this
id | serial_num | version | .....
1 | 1 | 1 | .....
2 | 2 | 1 | .....
3 | 2 | 2 | .....
4 | 3 | 1 | .....
5 | 4 | 1 | .....
6 | 5 | 1 | .....
7 | 5 | 2 | .....
8 | 5 | 3 | .....
Now what I want to select is to get rows with max version and unique serialn_num ...
The result would be:
id | serial_num | version | .....
1 | 1 | 1 | .....
3 | 2 | 2 | .....
4 | 3 | 1 | .....
5 | 4 | 1 | .....
8 | 5 | 3 | .....
My SQL is a bit more complicated and that is why I don't solve the problem by using MAX()... I have few left joins etc ...
any ideas?
Best regards and thank you for your time!
Try this:
SELECT yourtable.*
FROM yourtable
WHERE (serial_num, version) in (select serial_num, max(version)
from yourtable
group by serial_num)
Subquery will return the maximum version for serial_num, so this will return all rows where serial_num has the maximum value. See this fiddle.
You can use a subquery to find the max values and then join back to your table:
select t1.id,
t1.serial_num,
t1.version
from yourtable t1
inner join
(
select serial_num,
max(version) version
from yourtable
group by serial_num
) t2
on t1.serial_num = t2.serial_num
and t1.version = t2.version
See SQL Fiddle with Demo
Result:
| ID | SERIAL_NUM | VERSION |
-----------------------------
| 1 | 1 | 1 |
| 3 | 2 | 2 |
| 4 | 3 | 1 |
| 5 | 4 | 1 |
| 8 | 5 | 3 |
Selecting id for a group by query is useless. You should only select the column you are using in group by and other columns that are being applied aggregate functions.
Hope this works for you.
SELECT id,
serial_num,
Max(`version`) `version`
FROM tbl1
GROUP BY serial_num