SQL QUERY
select id, month_id, id_type,
max(case when immediate_prev <> id_type then immediate_prev
end) over (partition by id, id_type, (seqnum - seqnum_2)
) as id_type_prev
from (select *,
row_number() over (partition by id order by month_id) as seqnum,
row_number() over (partition by id, id_type order by month_id) as seqnum_2,
lag(id_type) over (partition by id order by month_id) as immediate_prev
from `my_table`
WHERE id = 123
)
ORDER BY month_id asc
my_table data
id|month_id|id_type
123|202001|aaa
123|202002|aaa
123|202003|aaa
123|202004|bbb
123|202005|bbb
123|202006|bbb
Query return data
id|month_id|id_type|id_type_prev
123|202001|aaa|null
123|202002|aaa|null
123|202003|aaa|null
123|202004|bbb|aaa
123|202005|bbb|aaa
123|202006|bbb|aaa
I have a SQL query that returns the previous id_type value for a given id. I would also like to know the month_id of the previous id_type but I am not sure how to get this information. Above is the table data and what my current query returns.
Below is the additional data I am after, I woud like help getting the month_id_prev added to my above query. This would be the previous id_type's most recent month_id.
id|month_id|id_type|id_type_prev|month_id_prev
123|202001|aaa|null|null
123|202002|aaa|null|null
123|202003|aaa|null|null
123|202004|bbb|aaa|202003
123|202005|bbb|aaa|202003
123|202006|bbb|aaa|202003
Consider the approach below using your sample data:
with sample_data as (
select 123 as id, 202001 as month_id, 'aaa' as id_type,
union all select 123 as id, 202002 as month_id, 'aaa' as id_type,
union all select 123 as id, 202003 as month_id, 'aaa' as id_type,
union all select 123 as id, 202004 as month_id, 'bbb' as id_type,
union all select 123 as id, 202005 as month_id, 'bbb' as id_type,
union all select 123 as id, 202006 as month_id, 'bbb' as id_type,
),
cte1 as (
select id, month_id, id_type,
max(case when immediate_prev <> id_type then immediate_prev
end) over (partition by id, id_type, (seqnum - seqnum_2)
) as id_type_prev,
latest_ym,
lag(latest_ym) over (partition by id order by month_id) as prev_ym
from
(select *,
row_number() over (partition by id order by month_id) as seqnum,
row_number() over (partition by id, id_type order by month_id) as seqnum_2,
lag(id_type) over (partition by id order by month_id) as immediate_prev,
last_value(month_id) over (partition by id,id_type order by id) as latest_ym
from sample_data)
)
select
id,
month_id,
id_type,
id_type_prev,
max(if(month_id > prev_ym, prev_ym, null)) over (partition by id,id_type) as month_id_prev
from cte1
order by month_id asc
Output:
Related
table1 has 3 columns in my database: id, category, timestamp. I need to query the newest 3 rows from each category:
WITH ranked_rows AS
(SELECT t.*, ROW_NUMBER() OVER (PARTITION BY category ORDER BY t.timestamp DESC) AS rn
FROM table1 AS t)
SELECT ranked_rows.* FROM ranked_rows WHERE rn<=3
now I need to select 10 partitions from the results randomly (please notice that each partition has 3 rows). how to do that?
There are various methods. One is:
WITH ranked_rows AS (
SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY category ORDER BY t.timestamp DESC) AS seqnum,
DENSE_RANK() OVER (ORDER BY MD5(category)) as catnum
FROM table1 t
)
SELECT ranked_rows.*
FROM ranked_rows
WHERE seqnum <= 3 AND catnum <= 10;
The md5() just makes the results look random.
if you want true random per category, here is one way :
with categorycte as (
select category , rand() randomcatid
from table1
group by category
),ranked_rows AS
(
SELECT t.*
, ROW_NUMBER() OVER (PARTITION BY category ORDER BY t.timestamp DESC) AS rn
, dense_rank() over (order by randomcatid) catnum
FROM table1 AS t
join categorycte c on t.category = c.category
)
SELECT ranked_rows.* FROM ranked_rows
WHERE rn<=3 and catnum <= 10;
I want to retrieve one result for each [Group] by the highest Time.
Result of current code:
SELECT [Group], ArticleNumber, max(TimeTrue) as Time
FROM PerformanceOpc (NOLOCK) WHERE ([Group]='Pack2' OR [Group]='70521-030')
GROUP BY [Group], ArticleNumber
UNION
SELECT [Group], ArticleNumber, max(StopTime) as Time
FROM StoppageOpc (NOLOCK) WHERE ([Group]='Pack2' OR [Group]='70521-030')
GROUP BY [Group], ArticleNumber
ORDER BY Time DESC
The result should be only two records (csv):
Group,ArticleNumber,Time
70521-030,,2021-03-15 13:50:15
Pack2,183026,2021-03-15 13:47:39
Hmmm . . . you would seem to want to union all before aggregating:
SELECT [Group], ArticleNumber, max(Time) as Time
FROM ((SELECT [Group], ArticleNumber, TimeTrue as Time
FROM PerformanceOpc
WHERE [Group] IN ('Pack2', '70521-030')
) UNION ALL
(SELECT [Group], ArticleNumber, StopTime as Time
FROM StoppageOpc
WHERE [Group] IN ('Pack2', '70521-030')
)
) g
GROUP BY [Group], ArticleNumber;
This returns one row per group and article, which seems to be what your query is doing.
If you really want only one row per group, then you want ROW_NUMBER() and not aggregation:
SELECT g.*
FROM (SELECT g.*, ROW_NUMBER() OVER (PARTITION BY [Group] ORDER BY time DESC) as seqnum
FROM ((SELECT [Group], ArticleNumber, TimeTrue as Time
FROM PerformanceOpc
WHERE [Group] IN ('Pack2', '70521-030')
) UNION ALL
(SELECT [Group], ArticleNumber, StopTime as Time
FROM StoppageOpc
WHERE [Group] IN ('Pack2', '70521-030')
)
) g
) g
WHERE seqnum = 1;
Try select top 1 with order by in temporal tables and then query them with union
SELECT top 1[Group], ArticleNumber, max(TimeTrue) as Time into #tmp1
FROM PerformanceOpc (NOLOCK) WHERE ([Group]='Pack2' OR [Group]='70521-030')
GROUP BY [Group], ArticleNumber
order by Time desc
SELECT top 1 [Group], ArticleNumber, max(StopTime) as Time into #tmp2
FROM StoppageOpc (NOLOCK) WHERE ([Group]='Pack2' OR [Group]='70521-030')
GROUP BY [Group], ArticleNumber
ORDER BY Time DESC
select * from #tmp1
union
select * from #tmp2
drop table #tmp1
drop table #tmp2
For example, we have 1, 2 and 3 are the most frequent values at the same time, how to return them when it is a tie?
id
1
1
1
2
2
2
3
3
3
4
You could try:
SELECT id
FROM yourTable
GROUP BY id
HAVING COUNT(*) = (SELECT COUNT(*) FROM yourTable
GROUP BY id ORDER BY COUNT(*) DESC LIMIT 1);
On more recent versions of MySQL 8+, we can use RANK here:
WITH cte AS (
SELECT id, RANK() OVER (ORDER BY COUNT(*) DESC) rnk
FROM yourTable
GROUP BY id
)
SELECT id
FROM cte
WHERE rnk = 1;
with DeleteDUplicateinXYZ
as
(
Select ID, rank()over( order by Id Asc) as [rank]
from ppp -----------never use 'partion by' while using rank
)Delete from DeleteDUplicateinXYZ
where [rank] in (Select id, count([rank])
from DeleteDUplicateinXYZ group by Id having count([rank]) >=2)
I have a query that returns an ID, item of highest value and maximum level that a user is on.
My query is as follows :
SELECT id,
MAX(item) AS highest_item,
MAX(level) AS highest_level
FROM data
GROUP BY 1
ORDER BY 1;
How can I query the database so that I receive a total count of unique users, who are on the same highest level and have the same highest value item?
You could get the count(distcint id) grouped by the values you need. Eg. for both the values:
select count(distinct id ), highest_item, highest_level
from (
SELECT id,
MAX(item) AS highest_item,
MAX(level) AS highest_item
FROM data
GROUP BY 1
) t
group by highest_item, highest_level
order by count(distinct id ) desc
or for highest_item
select count(distinct id ), highest_item
from (
SELECT id
MAX(item) AS highest_item,
MAX(level) AS highest_level
FROM data
GROUP BY 1
) t
group by highest_item
order by count(distinct id ) desc
of for highest_level
select count(distinct id ), highest_level
from (
SELECT id,
MAX(item) AS highest_item,
MAX(level) AS highest_level
FROM data
GROUP BY 1
) t
group by highest_level
order by count(distinct id ) desc
You can try this also
Select id,count(Id) from data group by level,item having level=max(level) and item=max(item)