Mysql update where each updated row has an increasing number - mysql

Is it possible to run a MySql query that updates certain rows, but gives the updated value in each row an increasing value.
I looked into stored procedures for this but I was not able to create such a procedure.
Here is a sample to help you better understand what i want to achieve:
The table
id text myCustomValue myMatchValue
1 Test1 1 a
2 Test2 2 a
3 Test3 3 a
4 Test4 1 b
5 Test5 1 c
6 Test6 2 b
7 Test7 3 b
My custom query should basically achieve this:
UPDATE table SET myCustomValue = increasingNumberStartingAt_5 WHERE myMatchValue = a;
With this query the result would be:
id text myCustomValue myMatchValue
1 Test1 5 a
2 Test2 6 a
3 Test3 7 a
4 Test4 1 b
5 Test5 1 c
6 Test6 2 b
7 Test7 3 b
I need this because the table is large and thus I cannot run many queries to the database to update each row individually. I could send multiple statements at once, but it seems like there should be a much simpler solution that i just cannot think of.

You can do something like this
UPDATE mytable e,
(SELECT #n := 4) m
SET e.myCustomValue = #n := #n + 1
WHERE e.myMatchValue ='a'
SQL-Fiddle

Try this:
UPDATE mytable AS t1
INNER JOIN (
SELECT id, #rn := #rn + 1 AS rn
FROM mytable
CROSS JOIN (SELECT #rn := 4) AS var
WHERE myMatchValue = 'a'
ORDER BY id
) AS t2 ON t1.id = t2.id
SET t1.myCustomValue = t2.rn
The above UPDATE statement uses an INNER JOIN to a derived table that uses a variable in order to enumerate matching records of the table. The first matching record is assigned a value of 5, next record a value of 6, etc.
Demo here

UPDATE YOUR_TABLE
INNER JOIN (
SELECT
T1.ID,
#a := #a + 1 AS incr
FROM
(SELECT #a := 4) sl,
YOUR_TABLE T1
INNER JOIN YOUR_TABLE T2 ON T1.ID = T2.ID
WHERE
T1.myMatchValue = 'a'
) filteredTable ON YOUR_TABLE.ID = filteredTable.ID
SET YOUR_TABLE.myCustomValue = filteredTable.incr;
RUNNING SQL FIDDLE

You could try this:
SET #start_at = 4; -- 1 minus your desired start point
UPDATE
my_table a
INNER JOIN (
SELECT
id, #start_at := #start_at + 1 AS _row
FROM
my_table
WHERE
myMatchValue = 'a' ) b
ON
a.id = b.id
SET
a.myCustomValue = b._row;
Here: sqlfiddle

Related

mysql removing duplicates with where clause

i am trying to remove duplicate records having same hid values.
Here's the Fiddle:
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=86e8ed00cf0a496da490eae5d7aae093
Table product_match_unmatches:
ID hid flag
1 1 1
2 1 1
3 2 1
4 2 1
5 1 2
6 2 2
7 2 2
8 1 1
9 1 1
10 2 1
Now I want to remove duplicates hid from the table but for flag = 1 only.
This query will remove all duplicates except for the recent one, but irrespective of flag values:
DELETE pmu1
FROM dmf_product_match_unmatches as pmu1
LEFT JOIN ( SELECT MAX(ID) as ID, hid
FROM dmf_product_match_unmatches as pmu2
GROUP BY hid) pmu3 USING (ID, hid)
WHERE pmu3.ID IS NULL;
I tried to add where clause flag = 1 in the above query but this is not producing desired result.
DELETE pmu1
FROM dmf_product_match_unmatches as pmu1
LEFT JOIN ( SELECT MAX(ID) as ID, hid
FROM dmf_product_match_unmatches as pmu2
where flag = 1
GROUP BY hid
) pmu3 USING (ID, hid)
WHERE pmu3.ID IS NOT NULL;
The required output is:
ID hid flag
5 1 2
6 2 2
7 2 2
9 1 1
10 2 1
Do you need in
DELETE t1
FROM dmf_product_match_unmatches t1
JOIN dmf_product_match_unmatches t2 USING (hid, flag)
WHERE flag = 1
AND t1.id < t2.id;
?
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=a5e9e95335573ebedd45cdcd577b5602
Using row_number
DELETE pmu1
FROM dmf_product_match_unmatches pmu1
JOIN (select id,
row_number() over(partition by hid order by id desc) rn
from dmf_product_match_unmatches
where flag = 1
) as pmu3 ON pmu1.ID = pmu3.ID
WHERE pmu3.rn > 1;
In sql server you can use the EXCEPT set operator:
declare #flag int = 1
delete dmf_product_match_unmatches
where id in (
select id
from dmf_product_match_unmatches
where flag = #flag
except
select max(id) id
from dmf_product_match_unmatches
where flag = #flag
group by hid, flag
)
In mysql you can use NOT EXISTS
declare #flag int = 1
delete d1
from dmf_product_match_unmatches d1
where flag = #flag
and not exists (
select max(id) id
from dmf_product_match_unmatches d2
group by hid, flag
having d1.id = max(d2.id)
)

SQL query to join two tables with no repeated values?

Table 1
ID | NAME | WARD_ID|
1 A 1
2 B 1
3 C 2
4 D 2
Table 2
ID | MONTH1 | MONTH2 | WARD_ID|
1 9 10 1
2 6 11 1
3 5 12 2
4 13 14 2
I want to join this two table and produce the following output:
ID | NAME | MONTH1 | MONTH2 | WARD_ID|
1 A 9 10 1
2 B 6 11 1
3 C 5 12 2
4 D 13 14 2
In the ON condition of the query I have to keep WARD_ID equal for both the tables. I could not able to figure out the solution. Anyone have any experience with a query like this?
I think you want something like this:
select t1.*, t2.*
from (select t1.*,
(#rn1 := if(#w1 = ward_id, #rn1 + 1,
if#w1 := ward_id, 1, 1)
)
) as rn
from (select t1.* from table1 t1 order by ward_id, id ) t1 cross join
(select #w1 := -1, #rn1 := -1) params
) t1 join
(select t2.*,
(#rn2 := if(#w2 = ward_id, #rn2 + 1,
if#w2 := ward_id, 1, 1)
)
) as rn
from (select t2.* from table2 t2 order by ward_id, id ) t2 cross join
(select #w2 := -1, #rn1 := -1) params
) t1
on t2.ward_id = t1.ward_id and t2.rn = t1.rn;
The subqueries enumerate the rows in each table. The join then uses the enumeration.
This is much simpler in MySQL 8.0, using row_number().
I'm assuming here that ID is intended to be the same from both tables. If so, I think you can do a multi-condition join:
select * from table1 t1
inner join table2 t2
on t1.ID=t2.ID and t1.WARD_ID=t2.WARD_ID
You can do something like:
SET #rn:=0;
SET #rn2:=0;
SELECT *
FROM (
SELECT #rn:=#rn+1 AS rn1, t1.ID, t1.NAME, t1.WARD_ID
FROM t1
GROUP BY t1.WARD_ID, t1.NAME
ORDER BY t1.WARD_ID, t1.NAME
) s1
INNER JOIN (
SELECT #rn2:=#rn2+1 AS rn2, t2.ID, t2.MONTH1, t2.MONTH2, t2.WARD_ID
FROM t2
GROUP BY t2.WARD_ID, t2.MONTH1,t2.MONTH2
ORDER BY t2.WARD_ID, t2.MONTH1,t2.MONTH2
) s2 ON s1.WARD_ID = s2.WARD_ID
AND s1.rn1 = s2.rn2
But it really doesn't reliably sort the tables to join the same rows every time. I still think there isn't a reliable/repeatable way to join the two tables the same every time.
============================================================
http://sqlfiddle.com/#!9/aa2db0/1 <<<< If ID can be used to reliably sort the two tables, you can use it in the ORDER BYs. I've added it in this Fiddle, and included rows in the setup that would fall before the existing records and potentially change the sorting. This also includes more records in Table 2 than there are in Table 1, so would possibly result in duplicated rows. These new rows are ignored since they can't be matched between tables.

Left outer join to two tables

I have a table 1 with a one to many relationship to table 2.
Table 1 also has a one to many relationship with table 3
I want to combine the results of the join but all im getting is repeated values
Here is the structure:
table 1
reportnumber
1
2
3
table 2
reportnumber col1
1 a
1 b
2 c
3 a
table 3
reportnumber col2
1 x
1 y
1 z
2 w
expected result set
reportnumber col1 col2
1 a x
1 b y
1 z
2 c w
3 a
I'm sure this is possible with a left outer join but i just cant get the syntax right
Any clues?
This is what im trying
select * from table1 a
left outer join table2 b on a.reportnumber=b.reportnumber
left outer join table3 on a.reportnumer=c.reportnumber
But the results look like this
reportnumber col1 col2
1 a x
1 a y
1 a z
1 b x
1 b y
1 b z
...
This isn't easy in MySQL, but you can do it with variables. This has little to do with a join. Or, it has a lot to do with join, but you don't have the right join keys and you don't have full outer join.
The solution is to enumerate the rows from each table with the data columns. Then aggregate using the enumeration and reportnumber:
select reportnumber, max(col1) as col1, max(col2) as col2
from ((select t2.reportnumber, col1, null as col2, #rn2 := #rn2 + 1 as rn
from table2 t2 cross join
(select #rn2 := 0) const
) union all
(select t3.reportnumber, null, t3.col2, #rn3 := #rn3 + 1 as rn
from table3 t3 cross join
(select #rn3 := 0) const
)
) t
group by reportnumber, rn;

Mysql update max value with group by

I have a simple table that has many rows already:
id grade ...
1 1 ...
2 2 ...
3 2 ...
4 1 ...
5 1 ...
Now i want to add a column "relative_order", which is the order in that grade. So the table becomes:
id grade ... relative_order
1 1 ... 1
2 2 ... 1
3 2 ... 2
4 1 ... 2
5 1 ... 3
After i add the column, all the relative_order becomes 0 first. How can i fill the relative_order column using update syntax?
I tried using inner join, but failed:
UPDATE table AS i
INNER JOIN(
SELECT max(relative_order) as mOrder,grade
FROM table
GROUP BY grade
) AS j
ON i.grade = j.grade
SET i.relative_order = j.mOrder + 1
You could use this SELECT query that will return the relative_order that you need:
SELECT
t1.id,
t1.grade,
COUNT(t2.id) relative_order
FROM
yourtable t1 INNER JOIN yourtable t2
ON t1.grade=t2.grade AND t1.id>=t2.id
GROUP BY
t1.id,
t1.grade
or if you want to update the value, you can join your table with the previous query, like this:
UPDATE
yourtable INNER JOIN (
SELECT
t1.id,
t1.grade,
COUNT(t2.id) relative_order
FROM
yourtable t1 INNER JOIN yourtable t2
ON t1.grade=t2.grade AND t1.id>=t2.id
GROUP BY
t1.id,
t1.grade) seq
ON yourtable.id=seq.id AND yourtable.grade=seq.grade
SET
yourtable.relative_order = seq.relative_order
Please see fiddle here.

Merging 2 result sets of colums of an mysql query into one

Example:
First Query:
select A,B,C from tb1;
---------------
A B C
---------------
1 1 3
2 1 4
Second Query:
select E from tb2;
---------------
E
---------------
8
9
The required result format should be like this:-
-----------------------
A B C E
-----------------------
1 1 3 8
2 1 4 9
Please tell me the query how to get the result set.
to make your tables better structured if you can add in both tables a column id to identify the row number of each table.
then you can easily merge two table which have same id . the relation here is the id column.
then you could do this
select A, B, C , E from Table1 t1
inner join Table2 t2
on t1.id = t2.id
please see structured tables in this DEMO HERE
THE RESULT:
A B C E
1 1 3 8
2 1 4 9
hope it helps you !
SQL tables are inherently unordered. This poses a problem, because there is nothing in your table to specify the ordering of the rows, which seems to be the connection between the two tables.
So, you have to hold your breath and make some assumptions. The particular assumption is that the data returned by a select is the actual order you want in the table (it could be different if you have deletes in the table or are running in a parallel environment).
The following code adds an id to each table. This id can then be used for the join:
select t1.A, t1.B, t1.C, t2.D
from (select t1.*, #rn := #rn + 1 as id
from tbl1 t1 cross join (select #rn := 0)
) t1 left outer join
(select t2.*, #rn := #rn + 1 as id
from tbl2 t2 cross join (select #rn := 0)
) t2
on t1.id = t2.id
Hi may be it's help for you
you can try like this
SELECT * FROM tb1,tb2
And you get output like
-----------------------
A B C E
-----------------------
1 1 3 8
2 1 4 9