So i have a table named "log" with the following columns,
id, endpoint ,response ,group
SAMPLE DATA.
1. endpoint1 ,{"last_name":"data here"} ,1234
2. endpoint2 ,{"first_name":"data here"} ,1234
3. endpoint3 ,{"dob":"12-21-2301"} ,1234
what I want to achieve is to write a query that can generate a record grouped by the "
group" column and the final output should be something like this.
{"last_name","data here","first_name":"data here","dob":"12-21-2301"}
for each record with each key been a column.
Thank you
WITH RECURSIVE
cte1 AS ( SELECT response,
`group`,
ROW_NUMBER() OVER (PARTITION BY `group`) rn
FROM log ),
cte2 AS ( SELECT response,
`group`,
rn
FROM cte1
WHERE rn = 1
UNION ALL
SELECT JSON_MERGE_PRESERVE(cte1.response, cte2.response),
cte1.`group`,
cte1.rn
FROM cte2
JOIN cte1 USING (`group`)
WHERE cte2.rn + 1 = cte1.rn )
SELECT DISTINCT
FIRST_VALUE(response) OVER (PARTITION BY `group` ORDER BY rn DESC) responses,
`group`
FROM cte2;
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=913b1923d7d5dbc7e42baeefb6e6ec86
Related
I need some comma separated values for one of my column :
Input :
id status
1. pause
1. start
1. running
2. pause
3. pause
Output:
id. status
1. pause,start,running
2. pause
3. pause
I do not want to use the group_concat function here as in future in it can be possible that will be using another type of database (sql/nosql).Can anyone help me to use any alternate method?
WITH RECURSIVE
cte1 AS (
SELECT id, status,
ROW_NUMBER() OVER (PARTITION BY id) rn
FROM test
),
cte2 AS (
SELECT id, rn,
CAST(status AS CHAR(65535)) csv
FROM cte1
WHERE rn = 1
UNION ALL
SELECT cte1.id, cte1.rn,
CONCAT_WS(',', cte2.csv, cte1.status)
FROM cte2
JOIN cte1 ON cte1.id = cte2.id AND cte1.rn = cte2.rn + 1
),
cte3 AS (
SELECT id, csv,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY rn DESC) rn
FROM cte2
)
SELECT id, csv
FROM cte3
WHERE rn = 1
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=0713abe3711c98c91dd1ceadb533e968
Another DBMSs needs minimal changes when adapting this query. Removing RECURSIVE from WITH clause definition, replacing CONCAT_WS() with according function (or maybe using common concatenation if statusis not nullable), removing explicit CAST in recursive CTE or changing the datatype...
PS. Another DBMSs have the function which is an analog of GROUP_CONCAT() in MySQL, or at least they have some specific constructions/methods for to perform such task.
I have a table like this:
MyTable:
id: pk
numero: varchar
data_modif: timestamp
...
I have multiple records with same value in numero and I need to return each distinct numero record with oldest data_modif. How can I do this?
This sounds like aggregation:
select numero, min(data_modif)
from mytable
group by numero;
If you want the entire row, then window functions are one method:
select t.*
from (select t.*,
row_number() over (partition by numero order by data_modif asc) as seqnum
from mytable t
) t
where seqnum = 1;
EDIT:
In an old version of MySQL, you woudl use:
select t.*
from t
where t.data_modif = (select min(t2.data_modif)
from t t2
where t2.numero = t.numero
);
I have a table with following structure
Date
train
time1
train1
time2
train2
time3
train1
time4
train2
I want to create a new table and keeping only the latest record of each distinct train
Date
train
time3
train1
time4
train2
How should I achieve so?
One method is for selecting the most recent rows is:
select t.*
from releng_retry_test_phases t
where t.date = (select max(t2.date) from releng_retry_test_phases t2 where t2.train = t.train);
If you actually want to modify the table and delete the older rows;
delete t
from releng_retry_test_phases t join
(select t2.train, max(date) as max_date
from releng_retry_test_phases t2
group by t2.train
) t2
using (train)
where t.date < t2.max_date;
You can use ROW_NUMBER() to identify the rows you want:
select date, train
from (
select *,
row_number() over(partition by train order by date desc) as rn
) x
where rn = 1
WITH temp As(
SELECT *, Row_Number() over (PARTITION BY train ORDER BY date DESC ) as
rowNumber FROM table
)
SELECT date, train FROM temp WHERE rowNumber = 1
You can use row_number() method.
I have a mysql table like below. It used to store document with versioning.
I want to select a docid of latest (with higest major version and minor version). It will eleminate all same doc id only fetch the document with highest major_version & minor_version. So i want result as below.
In MySQL 8.0, you can filter with row_number():
select *
from (
select
t.*,
row_number() over(partition by id, docid order by major_version, minor_version) rn
from mytable t
) t
where rn = 1
In earlier versions, you can filter with a correlated subquery. Assuming that you have a primary key in the table, say column pk, you can do:
select t.*
from mytable t
where t.pk = (
select t1.pk
from mytable t1
where t1.id = t.id and t1.docid = t.docid
order by t1.major_version desc, t1.minor_version desc
limit 1
)
For performance, consider an index on (id, docid, major_version, minor_version).
Without a unique column that can be used as primary key, it is a bit more complicated. One way to do it is to use not exists:
select t.*
from mytable t
where not exists (
select 1
from mytable t1
where
t1.id = t.id
and t1.docid = t.docid
and (
t1.major_version > t.major_version
or (t1.major_version = t.major_version and t1.minor_version > t.minor_version)
)
)
One method uses row_number():
select t.*
from (select t.*,
row_number() over (partition by docid order by major_version desc, minor_version desc) as seqnum
from t
) t
where seqnum = 1;
This is a pain in earlier versions. Probably the simplest and most efficient method is to use variables:
select t.*
from (select t.*,
(#rn := if(#d = docid, #rn + 1,
if(#d := docid, 1, 1)
)
) as rn
from (select t.*
from t
order by docid, major_version desc, minor_version desc
) t cross join
(select #rn := 0, #d := '') params
) t
where rn = 1;
I am using the following code in MySQL server to get entries between 2 to 5 from table 'new_table' but I am receiving 'missing parenthesis' error, I have checked every aspect.
SELECT * FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY salary ASC) AS row number
FROM pact
) as temp table name
WHERE rownumber IN (2,5)
if your using a MySql-Server there is nothing like ROW_NUMBER()
but you could try something like this (UNTESTET):
SELECT * FROM (
SELECT
#num := if(#type = type, #num + 1, 1) as rownumber
FROM pact
ORDER BY salary ASC
) as temp_table_name
WHERE rownumber IN (2,5)
You can't use space in alias
SELECT * FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY salary ASC) AS rownumber
FROM pact
) as temp_table_name
WHERE rownumber IN (2,5)