I have a table orders with jsonb field eventlog and I have another table ids_tmp with two columns old_id and new_id.
The jsonb eventlog field has attributes userId with values equal to old_id from ids_tmp within json array.
I have to change old_id'es to new_id'es in eventlog.
I have this script, but i dont understand how to put result json to specific row in orders
UPDATE orders g
SET eventlog = s.json_array
FROM (
SELECT
jsonb_agg(
CASE WHEN exists (select 1 from ids_tmp h where cast(h.old_id as varchar) = elems ->> 'userId') THEN
jsonb_set(elems, '{userId}', ( select cast(cast(h.new_id as varchar) as jsonb) from ids_tmp h where cast(h.old_id as varchar) = elems ->> 'userId' ))
ELSE elems END
) as json_array
FROM
orders,
jsonb_array_elements(eventlog) elems
) s
Found a solution
update orders o
set eventlog = (
SELECT
jsonb_agg(
CASE WHEN exists (select 1 from ids_tmp h where cast(h.old_idas varchar) = elems ->> 'userId') THEN
jsonb_set(elems, '{userId}', ( select cast(cast(h.new_id as varchar) as jsonb) from ids_tmp h where cast(h.old_id as varchar) = elems ->> 'userId' ))
ELSE elems END
) as json_array
FROM
jsonb_array_elements(o.eventlog) elems
)
where o.id in (
select d.id
from orders d,
jsonb_array_elements(eventlog) elems
where exists (select 1 from ids_tmp h where cast(h.old_id as varchar) = elems ->> 'userId')
)
;
You either need to join the orders rows from the FROM clause to the orders g that you're updating (by order id or something, in a WHERE statement):
UPDATE orders g
SET eventlog = s.json_array
FROM (
SELECT
o.id,
jsonb_agg(
CASE WHEN h.new_id IS NOT NULL
THEN jsonb_set(elems, '{userId}', h.new_id)
ELSE elems END
) as json_array
FROM
orders o,
LATERAL jsonb_array_elements(o.eventlog) elems,
LEFT JOIN ids_temp h ON h.old_id = (elems ->> 'userId')::int
GROUP BY
o.id
-- ^^^^^^^^ also necessary
) s
WHERE g.id = s.id;
-- ^^^^^^^^^^^
or you should use a subquery referencing g in the SET clause instead of using a FROM:
UPDATE orders g
SET eventlog = (
SELECT
jsonb_agg(
CASE WHEN h.new_id IS NOT NULL
THEN jsonb_set(elems, '{userId}', h.new_id)
ELSE elems END
)
FROM
jsonb_array_elements(g.eventlog) elems,
-- ^
LEFT JOIN ids_temp h ON h.old_id = (elems ->> 'userId')::int
)
Also I've taken the liberty to simplify that WHEN EXISTS(…) subquery into a left join.
the first picture is the table . second picture is the expected output.
conditions are 1. refids should be same. 2. for all the same ref ids (a.start,a.end &b.start,b.end) in the current and previous row. 3. should calculate the time difference which is greater than or equal to one day.
You want pairs of rows that match certain condition. You can perform a join to identify the pairs.
You don't say which version of MySQL you are using but in MySQL 8.x you can do:
with
x as (
select a.id
from my_table a
join my_table b on b.id = a.id + 1
and b.refid = a.refid
and (a.detail = 'a.end' and b.detail = 'a.start'
or a.detail = 'b.end' and b.detail = 'b.start')
)
select t.*
from my_table t
join x on t.id = x.id or t.id = x.id + 1
For MySQL 5.x you can do:
select t.*
from my_table t
join (
select a.id
from my_table a
join my_table b on b.id = a.id + 1
and b.refid = a.refid
and (a.detail = 'a.end' and b.detail = 'a.start'
or a.detail = 'b.end' and b.detail = 'b.start')
) x on t.id = x.id or t.id = x.id + 1
Somebody can guide me (maybe Simple and fast query if there is or some fast code) to convert my CSV data file (with commas separation):
1,A,C,Z,F,G
2,G,Q,R,C,
3,Z,G,Q,
4,C,F,
5,O,P,
6,O,X,Y,J,
7,A,P,X,
I have this table with ~1,000,000 records
like these 7 records that you see (In real Database A,B,C,... are words in string), Records 1 and 2 are common in G and C value and 2,3 and 1,3 and ...
I want to sync records if they have at least two common value like Records 1 & 2,3,4 (but record 5,6,7 haven't at least 2 shared values with others) and generate a list like this:
1 A C Z F G Q R
2 G Q R C A Z F
3 Z G Q A C F R
4 C F A Z G Q R
5 O P
6 O X Y J
7 A P X
at the end we must have 4 same records if we sort data and one others without sync:
1 A C F G Q R Z
2 A C F G Q R Z
3 A C F G Q R Z
4 A C F G Q R Z
5 O P
6 J O X Y
7 A P X
Maybe I do not use good term for my meaning, please see:
1 A C Z F G
2 G Q R C
record 1 has C and G common with Record 2 now 1 has not R and Q thus we must have 1 A C Z F G + Q and R and Record 2 has not A,Z and F thus we must have: 2 G Q R C + A,Z and F thus at the end we have:
1 A C Z F G Q R
2 G Q R C A Z F
I need all records Respectively in the queue from top to bottom.
wrote a delphi code but it is so slow.
Someone suggest me this groovy code:
def f=[:]
new File('Data.csv').readLines().each{
def items=it.split(',')
def name
items.eachWithIndex { String entry, int i ->
if(i==0){
name=entry
}
else if(entry){
if(!f[entry])
f[entry]=[]
f[entry]<<name
}
}
}
f.findAll {it.value.size()>1}
It is very fast (because of using a map file I think), but It only finds the common values.
If you would go for a SQL solution, then that csv data could be
put in a normalized table with the data unfolded per ID & WORD.
Once you have that, it becomes a matter of self-joining that table.
And concatinate the words back together in alphabetic order.
SqlFiddle test here
Not sure how fast this method would be on a table with 1000k records though.
But it's an interesting puzzle.
Sample data:
DROP TABLE IF EXISTS test_words;
CREATE TABLE IF NOT EXISTS test_words (
id int unsigned NOT NULL PRIMARY KEY,
words varchar(60) NOT NULL
);
INSERT INTO test_words (id, words) VALUES
(1,'A C Z F G'),
(2,'G Q R C'),
(3,'Z G Q'),
(4,'C F'),
(5,'P O'),
(6,'O X Y J'),
(7,'A P X');
Tally table with numbers:
DROP TABLE IF EXISTS tmp_numbers;
CREATE TEMPORARY TABLE IF NOT EXISTS tmp_numbers (
n int unsigned NOT NULL PRIMARY KEY
);
INSERT INTO tmp_numbers (n) VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10);
Unfolding the words:
DROP TABLE IF EXISTS test_words_unfolded;
CREATE TABLE test_words_unfolded (
word varchar(10) NOT NULL,
id int unsigned NOT NULL,
PRIMARY KEY (word, id)
);
INSERT INTO test_words_unfolded (word, id)
SELECT DISTINCT SUBSTRING_INDEX(SUBSTRING_INDEX(t.words,' ', nr.n),' ',-1) as word, t.id
FROM test_words AS t
JOIN tmp_numbers AS nr
ON CHAR_LENGTH(t.words) - CHAR_LENGTH(REPLACE(t.words,' ','')) >= nr.n - 1
AND SUBSTRING_INDEX(SUBSTRING_INDEX(t.words,' ', nr.n),' ',-1) != '';
Result table:
DROP TABLE IF EXISTS test_result;
CREATE TABLE IF NOT EXISTS test_result (
id int unsigned NOT NULL PRIMARY KEY,
words varchar(60) NOT NULL
);
INSERT INTO test_result (id, words)
SELECT q.id, GROUP_CONCAT(DISTINCT t3.word ORDER BY t3.word ASC SEPARATOR ' ') as words
FROM
(
SELECT t1.id, t2.id as id2
FROM test_words_unfolded t1
JOIN test_words_unfolded t2 ON t1.word = t2.word
GROUP BY t1.id, t2.id
HAVING COUNT(*) > 1 OR t1.id = t2.id
) q
LEFT JOIN test_words_unfolded t3 ON t3.id = q.id2
GROUP BY q.id
ORDER BY q.id;
SELECT *
FROM test_result
ORDER BY id;
Result:
id words
-- -----
1 A C F G Q R Z
2 A C F G Q R Z
3 A C F G Q R Z
4 A C F G Z
5 O P
6 J O X Y
7 A P X
Extra
To mark the words that have been added, the query to fill the result table becomes a bit more complicated.
SELECT
q2.id,
GROUP_CONCAT(DISTINCT CASE WHEN q2.ori = 1 THEN q2.word ELSE CONCAT('[',q2.word,']') END ORDER BY q2.word ASC SEPARATOR ' ') as words
FROM
(
SELECT
q1.id, t3.word,
MAX(CASE WHEN q1.id = t3.id THEN 1 ELSE 0 END) as ori
FROM
(
SELECT
t1.id, t2.id as id2
FROM test_words_unfolded t1
JOIN test_words_unfolded t2 ON t1.word = t2.word
GROUP BY t1.id, t2.id
HAVING COUNT(*) > 1 OR t1.id = t2.id
) q1
LEFT JOIN test_words_unfolded t3 ON t3.id = q1.id2
GROUP BY q1.id, t3.word
) q2
GROUP BY q2.id
ORDER BY q2.id;
Result:
id words
-- -----
1 A C F G [Q] [R] Z
2 [A] C [F] G Q R [Z]
3 [A] [C] [F] G Q [R] Z
4 [A] C F [G] [Z]
5 O P
6 J O X Y
7 A P X
Additional experiment here
I have a Sql table tblEMP (EmpID,FirstName, LastName, BranchID, DOB).
Now I want to get matches Emp details as following condition:
Here F = FirstName, L= LastName, B = BranchID, D = DOB
1) Matching :
F == F And
L == L And
B == B And
D == D
2) Probable :
F == F And
L == L And
(S == S or D == D )
3) Possible :
F != F And
L == L And
(S == S or D == D )
I have Added a filed MatchType and set its value as per Emp detail match.
I have completed this using Dataset comparison but it take more time to compare data.
I have used below code and in dsNameMerge I have all EmpDetail:
for (int i = 0; i < dsNameMerge.Tables[0].Rows.Count; i++)
{
if (i == dsNameMerge.Tables[0].Rows.Count - 1)
break;
DataRow dr = dsNameMerge.Tables[0].Rows[i];
DataRow dr1 = dsNameMerge.Tables[0].Rows[i + 1];
... Compare as per above condition and set MatchType and create a Dataset table and insert matched emp detail with MatchType in it.
}
Now I want to do this task using Stored procedure.
How can I do this thing in Stored procedure?
Thanks
SELECT
*
FROM
(
SELECT a, b, c
FROM ABC
WHERE f = '1'
LEFT JOIN
SELECT v, n, m
FROM VBN
WHERE g = '1'
ON (v = a)
);
I am trying to select from a table is is built on the fly from conditions, what is this kind of table called? Live table?
You can call it as subquery.
If you wanted to apply a name to this subquery you can use an alias or by creating a view.
SELECT
aJoinedTable.*
FROM
(
SELECT a, b, c
FROM ABC
WHERE f = '1'
LEFT JOIN
SELECT v, n, m
FROM VBN
WHERE g = '1'
ON (v = a)
) as aJoinedTable;