I have a table table_1
id contact_id
1 500
5 89
8 35
15 458
... ...
555 38
how I can mix contact_id, result for table_1
id contact_id
1 35
5 458
8 35
15 89
... ...
555 45
You can randomly assign the contact ids using variables or row_number() (in MySQL 8+):
select t1.id, tt1.contact_id
from (select t1.*, row_number() over (order by id) as seqnum
from table_1 t1
) t1 join
(select t1.*, row_number() over (order by rand()) as seqnum
from table_1 t1
) tt1
on t1.seqnum = tt1.seqnum;
Without much difficulty (but more typing), this can be transformed to use variables in earlier versions.
You can also incorporate this into an update statement, if you want to shuffle the values permanently.
EDIT:
I think you want:
update table1 t1 join
(select t1.id, tt1.contact_id
from (select t1.*, (#rn1 := #rn1 + 1) as seqnum
from (select * table_1 order by id) t1 cross join
(select #rn1 := 0) params
) t1 join
(select t1.*, (#rn2 := #rn2 + 1) as seqnum
from (select * from table_1 order by rand()) t1 cross join
(select #rn2 := 0) params
) tt1
on t1.seqnum = tt1.seqnum
) tt1
on tt1.id = t1.id
set t1.contact_id = tt1.contact_id;
Related
Table one
===================
id name
-------------------
1 m
2 m
3 a
4 u
5 g
Table two
===================
id name
-------------------
8 m
9 m
10 u
11 a
12 x
15 m
Expected result
===================
1 m 8
2 m 9
3 a 11
4 u 10
I need to find id from table 2 associated with table 1 by name. But ids from table 2 must be different.
If i make join i receive wrong intersections:
select t1.id as i1, t1.name, t2.id as i2 from t1
join t2 on t1.name = t2.name
i1 name i2
--------------------
'1','m','8'
'2','m','8'
'1','m','9'
'2','m','9'
'4','u','10'
'3','a','11'
'1','m','15'
'2','m','15'
I need this for tables synchronization from different systems.
You can use the following query:
SELECT t1.id, t1.name, t2.id
FROM (
SELECT id, name,
#rn1 := IF(#n = name, #rn1 + 1,
IF(#n := name, 1, 1)) AS rn1
FROM Table1
CROSS JOIN (SELECT #rn1 := 0, #n := '') AS vars
ORDER BY name, id) AS t1
INNER JOIN (
SELECT id, name,
#rn2 := IF(#n = name, #rn2 + 1,
IF(#n := name, 1, 1)) AS rn2
FROM Table2
CROSS JOIN (SELECT #rn2 := 0, #n := '') AS vars
ORDER BY name, id
) AS t2 ON t1.name = t2.name AND t1.rn1 = t2.rn2
ORDER BY t1.id
The query uses variables in order to simulate ROW_NUMBER() window function, currently not available in MySQL. Variables #rn1, #rn2 enumerate records that belong to the same name partition with an order determined by id field.
Demo here
Imagine a table just filled with ID's and created timestamps, how would I convert this over to MySQL?:
SELECT created AS col_a , LAG (created) OVER ( ORDER by created ) AS col_b
FROM tester
You can use a correlated subquery:
SELECT t1.created AS col_a,
(SELECT created
FROM tester AS t2
WHERE t2.created < t1.created
ORDER BY created DESC LIMIT 1) AS col_b
FROM tester AS t1
or, use variables:
SELECT t1.created AS col_a, t2.created AS col_b
FROM (
SELECT created, #rn1 := #rn1 + 1 AS rn
FROM tester
CROSS JOIN (SELECT #rn1 := 0) AS var
ORDER BY created) AS t1
LEFT JOIN (
SELECT created, #rn2 := #rn2 + 1 AS rn
FROM tester
CROSS JOIN (SELECT #rn2 := 0) AS var
ORDER BY created
) AS t2 ON t1.rn = t2.rn + 1
I have a table:
id name
1 a
2 a
3 a
4 b
5 b
6 c
I am looking for an update statement that will update name column to:
id name
1 a
2 a-2
3 a-3
4 b
5 b-2
6 c
In SQL Server I would use:
;with cte as(select *, row_number() over(partition by name order by id) rn from table)
update cte set name = name + '-' + cast(rn as varchar(10))
where rn <> 1
I am not strong in MySQL nonstandard queries.
Can I do something like this in MySQL?
You can do this:
UPDATE YourTable p
JOIN(SELECT t.id,t.name,count(*) as rnk
FROM YourTable t
INNER JOIN YourTable s on(t.name = s.name and t.id <= s.id)
GROUP BY t.id,t.name) f
ON(p.id = f.id)
SET p.name = concat(p.name,'-',f.rnk)
WHERE rnk > 1
This will basically use join and count to get the same as ROW_NUMBER() , and update only those who have more then 1 result(meaning the second,third ETC excluding the first)
In MySQL you can use variables in order to simulate ROW_NUMBER window function:
SELECT id, CONCAT(name, IF(rn = 1, '', CONCAT('-', rn))) AS name
FROM (
SELECT id, name,
#rn := IF(name = #n, #rn + 1,
IF(#n := name, 1, 1)) AS rn
FROM mytable
CROSS JOIN (SELECT #rn := 0, #n := '') AS vars
ORDER BY name, id) AS t
To UPDATE you can use:
UPDATE mytable AS t1
SET name = (
SELECT CONCAT(name, IF(rn = 1, '', CONCAT('-', rn))) AS name
FROM (
SELECT id, name,
#rn := IF(name = #n, #rn + 1,
IF(#n := name, 1, 1)) AS rn
FROM mytable
CROSS JOIN (SELECT #rn := 0, #n := '') AS vars
ORDER BY name, id) AS t2
WHERE t1.id = t2.id)
Demo here
You can also use UPDATE with JOIN syntax:
UPDATE mytable AS t1
JOIN (
SELECT id, rn, CONCAT(name, IF(rn = 1, '', CONCAT('-', rn))) AS name
FROM (
SELECT id, name,
#rn := IF(name = #n, #rn + 1,
IF(#n := name, 1, 1)) AS rn
FROM mytable
CROSS JOIN (SELECT #rn := 0, #n := '') AS vars
ORDER BY name, id) AS x
) AS t2 ON t2.rn <> 1 AND t1.id = t2.id
SET t1.name = t2.name;
The latter is probably faster than the former because it performs less UPDATE operations.
The next query will do it with less effort for the database:
UPDATE
tab AS tu
INNER JOIN
-- result set containing only duplicate rows that must to be updated
(
SELECT
t.id,
COUNT(*) AS cnt
FROM
tab AS t
-- join the same table by smaller id and equal value. That way you will exclude rows that are not duplicated
INNER JOIN
tab AS tp
ON
tp.name = t.name
AND
tp.id < t.id
GROUP BY
t.id
) AS tc
ON
tu.id = tc.id
SET
tu.name = CONCAT(tu.name, '-', tc.cnt + 1)
I have two tables:
exam_outline_items:
jml_quiz_pool:
Of all the things I've tried, this got me the closest:
select t1.sequence, t1.title, t2.q_cat, t2.q_count
from student_pl.exam_outline_items t1
cross join pe_joomla.jml_quiz_pool t2
where t1.exam_outline_id = 5 and t1.chapter_num > 0
and t2.q_id = 1109 and t2.q_count > 0
group by title
Which produces this result:
I just need those q_cat values to be different, like they are in the 2nd query.
Thanks in advance for your help.
You have to have something to connect them with. If you don't have such a column, you can simulate one by creating a rownumber with variables.
select sequence, title, q_cat, q_count from (
select t1.sequence, t1.title, #r1 := #r1 + 1 as rownumber
from student_pl.exam_outline_items t1
, (select #r1 := 0) var_init
where t1.exam_outline_id = 5 and t1.chapter_num > 0
order by t1.sequence
) a
inner join
(
select t2.q_cat, t2.q_count, #r2 := #r2 + 1 as rownumber
from pe_joomla.jml_quiz_pool t2
, (select #r2 := 0) var_init
where t2.q_id = 1109 and t2.q_count > 0
order by t2.q_cat
) b on a.rownumber = b.rownumber;
Also note, that I used order by in those queries. In a database you have no sort order unless you explicitly set it with order by.
I have this table where I only want to look at AB
ID CODE COUNT
102 AB 9
101 AB 8
100 AC 23 //not important!!!!
99 AB 7
98 AB 6
97 AB 5
96 AB 0
Conversed to this
ID NEWID CODE COUNT
102 102 AB 9
101 101 AB 8
99 100 AB 7
98 99 AB 6
97 98 AB 5
96 97 AB 0
Using this query:
SELECT t.ID, #NEWID := COALESCE(#NEWID - 1, t.ID) AS NEWID, t.CODE, t.COUNT
FROM
(SELECT ID, CODE, COUNT FROM some_table WHERE CODE = 'AB' ORDER BY ID DESC) t,
(SELECT #NEWID := NULL) _uv;
http://sqlfiddle.com/#!2/e0b8b/1/0
And now I want to count the difference of each consecutive NEWID.
So
Step 1: 9 - 8 = 1
Step 2: 8 - 7 = 1
Step 3: 7 - 6 = 1
Step 4: 6 - 5 = 1
Step 5: 5 - 0 = 5
I'm used to doing this with
LEFT OUTER JOIN some_table t2 ON t.ID = ( t2.ID + 1 )
And then taking the difference between t2.count and t.count,
but now when I'm using COALESCE, I cannot select this NEWID, so the code below does not work.
LEFT OUTER JOIN some_table t2 ON t.NEWID = ( t2.NEWID + 1 )
So how should I resolve this issue?
Oh, so that's why you needed sequential IDs. Well, you can use user variables for this, too, and you don't even need NEWID! Since you're doing stuff like this, you'd do well to read up on how user variables work.
SELECT
t.ID, t.CODE, t.COUNT,
#PREVCOUNT - t.COUNT DIFFERENCE,
#PREVCOUNT := t.COUNT -- Updates for the next iteration, so it
-- must come last!
FROM
(SELECT ID, CODE, COUNT FROM some_table WHERE CODE = 'AB' ORDER BY ID DESC) t,
(SELECT #PREVCOUNT := NULL) _uv;
SQL Fiddle
Try this:
SELECT
t1.ID as ID1,
t2.ID as ID2,
t1.CODE as CODE,
t1.COUNT as C1,
t2.COUNT as C2,
t2.COUNT - t1.COUNT as DIFF
FROM
some_table t1
INNER JOIN some_table t2 ON t1.ID < t2.ID AND t1.CODE = t2.CODE
WHERE
t1.CODE='AB'
AND NOT EXISTS
(SELECT * FROM some_table t3
INNER JOIN some_table t4 ON t3.ID < t4.ID and t3.CODE = t4.CODE
WHERE
t3.CODE='AB'
AND t1.ID = t3.ID
AND t4.ID < t2.ID
)
ORDER BY t1.ID
Another way will be to use LIMIT:
SELECT
t.ID1 AS ID,
t.CODE as CODE,
t.C2-t.C1 AS DIFF
FROM
(
SELECT
t1.ID as ID1,
t1.CODE as CODE,
t1.COUNT as C1,
(SELECT t.COUNT
FROM some_table t
WHERE t.ID > t1.ID AND t.CODE=t1.CODE
ORDER BY t.ID
LIMIT 1) as C2
FROM
some_table t1
WHERE
t1.CODE='AB'
ORDER BY t1.ID) t
ORDER BY t.ID1
http://sqlfiddle.com/#!2/e0b8b/24