I've got a table, as such:
|id|jobid|statusid| ... other irrelevant rows...
|1 |123 | 1 |
|2 |321 | 2 |
|3 |123 | 2 |
|4 |321 | 3 |
|5 |123 | 3 |
Due to some unfortunate user error, they ended up using (for example) status 3 on some 500 jobs when the policy is to use status 4 following a status 2.
How would I go about joining a row to the previous row matching its value in the column "jobid" when there is an uncertain distance between it and the row before it, given that the value in "statusid" is 3? The goal being to update the table so that any 3 following a 2 with the same jobid (regardless of distance between ids) will be changed to a 4.
My desired output would be to join row 4 and 2 as well as 5 and 3.
(I'm aware the example is consistently id-2, that is not the case in my database.)
So far the relationship would be
SELECT mt.id, mt3.id
FROM mytable mt
INNER JOIN (SELECT MAX(mt1.id) AS mid, mt1.jobid
FROM mytable mt1
WHERE mt1.id < mt.id
GROUP BY mt1.jobid) mt2
ON mt2.jobid = mt.jobid
INNER JOIN mytable tm3
ON mt3.id=mt2.mid
AND mt3.statusid = 2
WHERE mt.statusid=3
But the line in the subquery reading
"WHERE sh1.id < mt.id"
is a relationship that can't exist as mt.id originated outside the subquery.
How can I get this query to work?
Thank you!
You can join to the previous row using a correlated subquery and another join. The following puts the two records on the same row:
select t.*, tprev.*
from (select t.*,
(select t2.id
from mytable t2
where t2.jobid = t.jobid and t2.id < t.id
order by t2.id desc
limit 1
) as prev_id
from mytable t
) t left join
mytable tprev
on t.id = tprev.prev_id;
Related
I am trying to restore the correct order in one table after certain set of modifications. I need to use UPDATE .. ORDER BY logic, but the field is in another table so INNER JOIN is required. mySQL does not like below syntax, is there any way to accomplish the same ?
SET #newOrder = 0;
UPDATE job T1 INNER JOIN job_schedule T2 ON T1.id = T2.jobID SET T1.order = (#newOrder:=#newOrder+1) WHERE T1.id = 100 ORDER BY T2.scheduledTime ASC
job table:
id actvity order
-------------------------
1 TestEngine 2
2 TestElectricity 1
job_schedule table:
id scheduledTime
-------------------------
1 2022-01-01 10:00:00
2 2022-01-01 11:00:00
After UPDATE, expected results should be:
id actvity order
-------------------------
1 TestEngine 1
2 TestElectricity 2
I have a table like this in MYSQL:
ID | NAME | VALUE |
----------------------------
1 | Bob | 1 |
2 | Bob | 2 |
3 | Jack | 5 |
4 | Jack | 8 |
5 | Jack | 10 |
and I'm trying to update the VALUE column to the highest value of rows with same NAME. So the result should be:
ID | NAME | VALUE |
----------------------------
1 | Bob | 2 |
2 | Bob | 2 |
3 | Jack | 10 |
4 | Jack | 10 |
5 | Jack | 10 |
I managed to get the max value like this:
SELECT MAX(Value) max FROM `table` GROUP BY Name having count(*) >1 AND MAX(Value) != MIN(Value)
But can't figure out how to put it in my update
Update table set Value = (SELECT MAX(Value) max FROM `table` GROUP BY Name having count(*) >1 AND MAX(Value) != MIN(Value))
Doesn't work. I'd appreciate any help.
This is easier than other answers are making it.
UPDATE MyTable AS t1 INNER JOIN MyTable AS t2 USING (Name)
SET Value = GREATEST(t1.Value, t2.Value);
You don't have to find the largest value. You just have to join each row to the set of rows with the same name, and set the Value to the greater Value of the two joined rows. This is a no-op on some rows, but it will apply to every row in turn.
http://sqlfiddle.com/#!9/f79a3/1
UPDATE t1
INNER JOIN (SELECT name, MAX(`value`) max_value
FROM t1 GROUP BY name) t2
ON t1.name = t2.name
SET t1.value = t2.max_value;
Create a temporary table consisting of ID NAME and MAX VALUE as follows:
CREATE TEMP TABLE TABLE1 AS
(SELECT NAME,MAX(Value) value FROM `table` GROUP BY Name having count(*) >1
AND MAX(Value) != MIN(Value)
);
Use this temporary table to do your update as follows:
UPDATE
Table_A
SET
Table_A.value = Table_B.value
FROM
`table` AS Table_A
INNER JOIN TABLE1 AS Table_B
ON Table_A.NAME = Table_B.NAME
Also this code is somewhat of an approximation as i am not familiar with mysql but i am familiar with sql.
Let me know if this doesn't help.
Simple left join would do the trick.
Try this out and let me know in case of any queries.
select a.id,a.name,b.value
from
table a
left join
(select name,max(value) as value from table group by name) b
on a.name=b.name;
You may use this query. The table is joined with a subquery (table t2) that contains the results you want to update your table with:
UPDATE `table` t1,
(SELECT Name, MAX(Value) maxv, MIN(Value) minv
FROM `table`
GROUP BY Name
HAVING COUNT(*)>1 AND maxv != minv) t2
SET t1.Value = t2.maxv
WHERE t1.Name = t2.Name;
If you want to know how will the values be updated, you can first run an equivalent SELECT query:
SELECT t1.*, t2.maxv
FROM `table` t1,
(SELECT Name, MAX(Value) maxv, MIN(Value) minv
FROM `table`
GROUP BY Name
HAVING COUNT(*)>1 AND maxv != minv) t2
WHERE t1.Name = t2.Name;
This query will display all the fields of table, followed by the new value maxv. You can check the current value and the new value, and if it looks fine, you may run the UPDATE query.
I need to find all attributes & image(s) for a product.
Every product is marked as such in the column type in Table 1.
The attributes are also defined in Table 1, each attribute on a seperate row.
This is a simplified version of the table structures:
Table 1:
id | type | value | url
1 | product | T-shirt |
2 | image | | http://www......
........
15 | size | XXL |
........
18 | color | blue |
Table 2:
id | ref_id | link_id
1 | 1 | 1
2 | 1 | 2
3 | 1 | 15
4 | 1 | 18
The relationship between a product and its attributes is defined in Table 2:
- ref_id matches the id in Table 1 for the product we want
- link_id holds an id (from Table 1) which is either the product itself or an attribute of the product
So in this example, id 1 in Table 1 has 4 occurences in Table 2 (ref_id = 1): the product row and 3 attribute rows (image, size & color)
They are referenced by the column link_id in Table 2.
I would like to solve this in 1 query if possible, but I am stuck at how to solve the 'back-reference'.
Once I have found a product's id in Table 1, I can get the link_id's in Table 2 allright, but how do I use those again (in the same query) to get the rows from Table 1.
Is this at all possible in 1 query, or should I use 2 seperate queries for this?
UPDATE:
this is how far I have come:
SELECT t1.id, t1.type, t1.value, t1.url,
t2.link_id
FROM table_1 t1
LEFT JOIN table_2 t2
ON t1.id = t2.ref_id
WHERE t1.type = 'product'
But after that I don't know how to construct the rest of the query based on the 'back-reference'.
You can join back to table_1 again
SELECT t1.id, t1.type, t1.value, t1.url,
t2.link_id, t1_attributes.type, t1_attributes.value
FROM table_1 t1
LEFT JOIN table_2 t2
ON t1.id = t2.ref_id
LEFT JOIN table_1 t1_attributes ON t2.link_id = t1_attributes.id
WHERE t1.type = 'product'
This will get you 1 row for each attribute though. If you want a field for each type of attribute, you'll have to do a join for each one.
SELECT t1.id, t1.type, t1.value, t1.url,
t2.link_id, t1_image.value, t1_size.value
FROM table_1 t1
LEFT JOIN table_2 t2 ON t1.id = t2.ref_id
LEFT JOIN table_1 t1_image ON t2.link_id = t1_image.id
LEFT JOIN table_1 t1_size ON t2.link_id = t1_size.id
WHERE t1.type = 'product' AND t1_image.type = 'image' AND
t1_size.type = 'size'
My SQL Skills are next to none. After looking around for the past 2 hours trying to figure this out I need some help please.
I have 2 tables as below
Table1 Table2
ID | Name Status_id
----------- ----------
1 | Open 1
2 | Closed 2
3 | On-Hold 1
What I would like to do is count the status_id in table 2 and group by the status_id. Then add the Name where the ID matches in the first column.
What I have at the moment is
SELECT status_id, COUNT(*) AS 'num' FROM table2 GROUP BY status_id
This is great so far and returns
1 | 2
2 | 1
What I need to return is
Open | 2
Closed | 1
I hope that is clear. Can anyone help?
Many thanks!
SELECT a.name, COUNT(*) AS num FROM table2 b
INNER JOIN table1 a
ON b.status_id=a.id
GROUP BY status_id
In the case that you want to also have Zero for On-Hold you'd need to do a LEFT join and count the a column from table2 instead of *
SELECT t1.name,
Count(t2.Status_id) AS num
FROM table1 t1
LEFT JOIN table2 t2
ON t1.id = t2.Status_id
GROUP BY t1.name;
DEMO
I am trying to build a mysql query to list all column a's that have a duplicate column b from a single table. The trick is I have a timestamp on the rows so i need to essentially identify which is the older of the duplicates so i can delete it. Any help would be appreciated.
Just example - this query return duplicate posts, now you just need to execute delete
id| title | text_desc | created
-------------------------------------------------------
1 | The title | description here |2012-02-21 10:58:58
2 | The title | description here 1 |2012-02-21 10:58:58
3 | The title | description here 3 |2012-02-21 10:58:58
select bad_rows.*
from posts as bad_rows
inner join (
select title, MIN(id) as min_id
from posts
group by title
having count(*) > 1
) as good_rows on good_rows.title = bad_rows.title
and good_rows.min_id <> bad_rows.id;
Here is the return rows
id| title | text_desc | created
-------------------------------------------------------
2 | The title | description here 1 |2012-02-21 10:58:58
3 | The title | description here 3 |2012-02-21 10:58:58
Here's your query:
DELETE FROM tablename
WHERE id IN
(SELECT t1.id
FROM tablename t1
JOIN tablename t2
ON t2.cola = t1.cola AND t2.colb = t1.colb
AND t2.timecol > t1.timecol
WHERE t1.cola = t1.colb)
The SELECT statement returns records where cola = colb and there are other matching rows with a later date. The DELETE statement deletes all records returned by the SELECT.
If you're looking to remove duplicate cola, then this is the query:
DELETE FROM tablename
WHERE id IN
(SELECT t1.id
FROM tablename t1
JOIN tablename t2
ON t2.cola = t1.cola
AND t2.timecol > t1.timecol)
SELECT FOOCODE,COUNT(*) AS DUPS
FROM TABLE
GROUP BY FOOCODE
HAVING COUNT(FOOCODE)>1;
The above query will return u all the duplicates.Is this what u are looking for?