I have a table:
id cod_pr Date nr
-------------------------------
1 22 12.10.2012 2
2 25 12.10.2012 3
3 22 12.11.2012 5
4 25 12.11.2012 2
5 22 12.12.2012 4
6 23 12.10.2012 3
How kan I select only max Date from each cod_pr?
select cod_pr,MAX(Date) from Table
group by cod_pr
If you want all columns, you can use ROW_NUMBER in a CTE:
WITH CTE AS
(
SELECT id,cod_pr,Date,nr,
ROW_NUMBER() OVER (PARTITION BY cod_pr ORDER BY Date DESC) AS RN
FROM dbo.Table
)
SELECT id,cod_pr,Date,nr, FROM CTE WHERE RN = 1
Otherwise you can simply use GROUP BY
SELECT cod_pr, MAX(Date) AS MaxDate
FROM dbo.Table
GROUP BY cod_pr
Related
I am trying to create a query for getting the current streak in MySQL based on status
ID
Dated
Status
1
2022-03-08
1
2
2022-03-09
1
3
2022-03-10
0
4
2022-03-11
1
5
2022-03-12
0
6
2022-03-13
1
7
2022-03-14
1
8
2022-03-16
1
9
2022-03-18
0
10
2022-03-19
1
11
2022-03-20
1
In the above table current streak should be 2( i.e 2022-03-20 - 2022-03-19) based on status 1. Any help or ideas would be greatly appreciated!
WITH cte AS (
SELECT SUM(Status) OVER (ORDER BY Dated DESC) s1,
SUM(NOT Status) OVER (ORDER BY Dated DESC) s2
FROM table
)
SELECT MAX(s1)
FROM cte
WHERE NOT s2;
SELECT DATEDIFF(MAX(CASE WHEN Status THEN Dated END),
MAX(CASE WHEN NOT Status THEN Dated END))
FROM table
and so on...
This is a gaps and islands problem. In your case, you want the island of status 1 records which occurs last. We can use the difference in row numbers method, assuming you are using MySQL 8+.
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY Dated) rn1,
ROW_NUMBER() OVER (PARTITION BY Status ORDER BY Dated) rn2
FROM yourTable
),
cte2 AS (
SELECT *, RANK() OVER (ORDER BY rn1 - rn2 DESC) rnk
FROM cte
WHERE Status = 1
)
SELECT ID, Dated, Status
FROM cte2
WHERE rnk = 1
ORDER BY Dated;
Demo
We can use 2 one row CTE's to find the latest date where the status was not the same as the latest one and then count the records superieur.
**Schema (MySQL v8.0)**
create table t(
ID int,
Dated date,
Status int);
insert into t values
(1,'2022-03-08',1),
(2,'2022-03-09',1),
(3,'2022-03-10',0),
(4,'2022-03-11',1),
(5,'2022-03-12',0),
(6,'2022-03-13',1),
(7,'2022-03-14',1),
(8,'2022-03-16',1),
(9,'2022-03-18',0),
(10,'2022-03-19',1),
(11,'2022-03-20',1);
---
**Query #1**
with latest AS
(SELECT
dated lastDate,
status lastStatus
from t
order by dated desc
limit 1 ),
lastDiff as
(select MAX(dated) diffDate
from t,latest
where not status = lastStatus
)
select count(*)
from t ,lastDiff
where dated > diffDate;
| count(*) |
| -------- |
| 2 |
---
[View on DB Fiddle](https://www.db-fiddle.com/)
We could also consider using datediff() to find the number of days that the streak has lasted which might be more interesting than count() seeing as there are some days where there is no record.
Trying to get the 2nd transaction month details for all the customers
Date User_id amount
2021-11-01 1 100
2021-11-21 1 200
2021-12-20 2 110
2022-01-20 2 200
2022-02-04 1 50
2022-02-21 1 100
2022-03-22 2 200
For every customer get all the records in the month of their 2nd transaction (There can be multiple transaction in a month and a day by a particular user)
Expected Output
Date User_id amount
2022-02-04 1 50
2022-02-21 1 100
2022-01-20 2 200
You can use dense_rank:
select Date, User_id, amount from
(select *, dense_rank() over(partition by User_id order by year(Date), month(date)) r
from table_name) t
where r = 2;
Fiddle
If dense_rank is an option you can:
with cte1 as (
select *, extract(year_month from date) as yyyymm
from t
), cte2 as (
select *, dense_rank() over (partition by user_id order by yyyymm) as dr
from cte1
)
select *
from cte2
where dr = 2
Note that it is possible to write the above using one cte.
Hi I have this table.
id lat lng userId
1 12 23 1
2 45 34 2
3 42 34 3
4 33 34 1
5 36 79 2
6 53 98 2
7 23 90 3
8 23 67 1
Here we have three users. (user ids 1,2,3). I want to get lateset record (id column max value) of each user.
My excepted output is this
userId lat lng
1 23 67
2 53 98
3 23 90
This query will give me group by option
SELECT
*
FROM
covid.locations
GROUP BY userId;
But how do I combine this with MAX(id) function.
One way is to use the following:
SELECT
cl.*
FROM covid.locations cl
INNER JOIN (
SELECT
userid
, MAX( id ) mid
FROM covid.locations
GROUP BY
userId
) g ON cl.userid = g.userid
AND cl.id = cl.mid
Another is to use row_number() over()
SELECT
userId
, lat
, lng
FROM (
SELECT
*
, ROW_NUMBER() OVER (PARTITION BY userid ORDER BY id DESC) rn
FROM covid.locations
GROUP BY
userId
) d
WHERE rn = 1
Both will identify the "most recent" row in the source table based in the id column of that table. Note that the second query requires MySQL version 8+ as this is when row_number() became supported in that database. The first query should run in dbms supporting SQL.
This will do
SELECT
*
FROM
covid.locations
where id in (select max(t.id) from covid.locations t group by t.userId)
order by id desc;
An example of the above query can be found in this SQLFiddle
please help me.
imagine the table as bellow
id name date_join
1 joni 2020-01-01
2 dani 2020-01-01
3 fani 2020-01-02
4 rina 2020-01-02
5 budi 2020-01-02
6 john 2020-01-03
7 dita 2020-01-03
8 sani 2020-01-05
9 soni 2020-01-06
10 aple 2020-01-06
11 rita 2020-01-06
12 hari 2020-01-06
and I want to query and show result like this
dates total_member
2020-01-01 2
2020-01-02 5
2020-01-03 7
2020-01-04 7
2020-01-05 8
2020-01-06 12
2020-01-07 12
I dont know how to write query to show result like that.
I used (date_join) as dates, count(id) and group by date(date_join) and the result not show like that.
In MySQL 8.0, you can solve this with aggregation and a window sum:
select
date_join,
sum(count(*))) over(order by date_join) total_members
from mytable
group by date_join
order by date_join
Or even without aggregation:
select date_join, total_members
from (
select
date_join,
count(*) over(order by date_join, name) total_members,
row_number() over(order by date, name desc) rn
from mytable
) t
where rn = 1
order by date_join
In earlier versions, one option is to select the distinct dates and use a correlated subquery to get the running count:
select
date_join,
(select count(*) from mytable t1 where t1.date_join <= t.date_join) total_members
from (select distinct date_join from mytable) t
I guess that would be pretty simple like this :
select date_join `dates`, count(*) `total_member`
from yourtable
group by date_join
order by total_member asc
You need to generate all the dates and then use aggregation:
select d.dte, sum(count(*)) over (order by d.dte)
from (select '2020-01-01' as dte union all
select '2020-01-02' as dte union all
select '2020-01-03' as dte union all
select '2020-01-04' as dte union all
select '2020-01-05' as dte union all
select '2020-01-06' as dte union all
select '2020-01-07' as dte
) d left join
t
on d.dte <= t.date_join
group by d.dte;
SELECT detailsID,`Topic 1 Scores`, MAX(Date) as "Date"
FROM Information.scores
WHERE `Topic 1 Scores` IS NOT NULL
GROUP BY `detailsID`,`Topic 1 Scores`
Is printing;
detailsID, Topic 1 Scores, MAX(Date)
2 0 26/09/2017
2 45 26/09/2017
2 100 26/09/2017
3 30 25/09/2017
3 80 14/10/2017
Rather than actually selecting the most recent date per detailsID which would be:
2 100 26/09/2017
3 80 14/10/2017
I want to retrieve TOPIC 1 SCORES with the most recent score (excluding null) (sorted by date) for each detailsID, (there are only detailsID 2 and 3 here, therefore only two results should return)
Solution 1 attempt
Inner subquery
You can do this:
SELECT t1.detailsID, t1.`Topic 1 Scores`, t1.date
FROM scores as t1
INNER JOIN
(
SELECT detailsID, MAX(date) as "LatestDate"
FROM scores
WHERE `Topic 1 Scores` IS NOT NULL
GROUP BY `detailsID`
) AS t2 ON t1.detailsID = t2.detailsID AND t1.date = t2.LatestDate
Demo
The subquery will give you the most recent date for each detailsID then in the outer query, there is a join with the original table to eliminate all the rows except those with the most recent date.
Update:
There are some rows with the same latest date, thats why you will have multiple rows with the same date and the same detailsID, to solve this you can add another aggregate for the score, so that you have only one row for each details id with the latest date and max score:
SELECT t1.detailsID, t1.`Topic 1 Scores`, t1.date
FROM scores as t1
INNER JOIN
(
SELECT detailsID, MAX(`Topic 1 Scores`) AS MaxScore, MAX(date) as "LatestDate"
FROM scores
WHERE `Topic 1 Scores` IS NOT NULL
GROUP BY `detailsID`
) AS t2 ON t1.detailsID = t2.detailsID
AND t1.date = t2.LatestDate
AND t1.`Topic 1 Scores` = t2.MaxScore
updated demo
Results:
| detailsID | Topic 1 Scores | date |
|-----------|----------------|------------|
| 2 | 100 | 2017-09-26 |
| 3 | 80 | 2017-10-14 |
WITH MYCTE AS
(
SELECT DetailsId, [Topic 1 Score], ROW_NUMBER() OVER ( Partition BY DetailsID ORDER BY DATE DESC) Num
FROM Scores
)
SELECT * FROM MYCTE WHERE num = 1
GO