SQL retrieve recent record - sql

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)

What about getting rid of Topic 1 Scores in GROUP BYdetailsID,Topic 1 Scores ?

Use a subquery to get the max and then join to it.
SELECT a.detailsID,`Topic 1 Scores`, a.Date
FROM Information.scores AS a
JOIN (SELECT detailsID, MAX(Date) "MaxDate"
FROM Information.scores
WHERE `Topic 1 Scores` IS NOT NULL
GROUP BY detailsID) Maxes
ON a.detailsID = Maxes.detailsID
AND a.Date = Maxes.MaxDate
WHERE `Topic 1 Scores` IS NOT NULL

Assuming SQL Server:
SELECT
ROW_NUMBER() OVER (PARTITION BY detailsID ORDER BY Date DESC) AS RowNumber,
detailsID, Date, Topic 1 Scores
FROM
Information.scores

Try doing
SELECT detailsID,`Topic 1 Scores`, MAX(Date) as "Date" GROUP BY "Date"

Related

How can I obtain the minimum date for a value that is equal to the maximum date?

I am trying to obtain the minimum start date for a query, in which the value is equal to its maximum date. So far, I'm able to obtain the value in it's maximum date, but I can't seem to obtain the minimum date where that value remains the same.
Here is what I got so far and the query result:
select a.id, a.end_date, a.value
from database1 as a
inner join (
select id, max(end_date) as end_date
from database1
group by id
) as b on a.id = b.id and a.end_date = b.end_date
where value is not null
order by id, end_date
This result obtains the most recent record, but I'm looking to obtain the most minimum end date record where the value remains the same as the most recent.
In the following sample table, this is the record I'd like to obtain the record from the row where id = 3, as it has the minimum end date in which the value remains the same:
id
end_date
value
1
02/12/22
5
2
02/13/22
5
3
02/14/22
4
4
02/15/22
4
Another option that just approaches the problem somewhat as described for the sample data as shown - Get the value of the maximum date and then the minimum id row that has that value:
select top(1) t.*
from (
select top(1) Max(end_date)d, [value]
from t
group by [value]
order by d desc
)d
join t on t.[value] = d.[value]
order by t.id;
DB<>Fiddle
I'm most likely overthinking this as a Gaps & Island problem, but you can do:
select min(end_date) as first_date
from (
select *, sum(inc) over (order by end_date desc) as grp
from (
select *,
case when value <> lag(value) over (order by end_date desc) then 1 else 0 end as inc
from t
) x
) y
where grp = 0
Result:
first_date
----------
2022-02-14
See running example at SQL Fiddle.
with data as (
select *,
row_number() over (partition by value) as rn,
last_value(value) over (order by end_date) as lv
from T
)
select * from data
where value = lv and rn = 1
This isn't looking strictly for streaks of consecutive days. Any date that happened to have the same value as on final date would be in contention.

How to choose max of one column per other column

I am using SQL Server and I have a table "a"
month segment_id price
-----------------------------
1 1 100
1 2 200
2 3 50
2 4 80
3 5 10
I want to make a query which presents the original columns where the price will be the max per month
The result should be:
month segment_id price
----------------------------
1 2 200
2 4 80
3 5 10
I tried to write SQL code:
Select
month, segment_id, max(price) as MaxPrice
from
a
but I got an error:
Column segment_id is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause
I tried to fix it in many ways but didn't find how to fix it
Because you need a group by clause without segment_id
Select month, max(price) as MaxPrice
from a
Group By month
as you want results per each month, and segment_id is non-aggregated in your original select statement.
If you want to have segment_id with maximum price repeating per each month for each row, you need to use max() function as window analytic function without Group by clause
Select month, segment_id,
max(price) over ( partition by month order by segment_id ) as MaxPrice
from a
Edit (due to your lastly edited desired results) : you need one more window analytic function row_number() as #Gordon already mentioned:
Select month, segment_id, price From
(
Select a.*,
row_number() over ( partition by month order by price desc ) as Rn
from a
) q
Where rn = 1
I would recommend a correlated subquery:
select t.*
from t
where t.price = (select max(t2.price) from t t2 where t2.month = t.month);
The "canonical" solution is to use row_number():
select t.*
from (select t.*,
row_number() over (partition by month order by price desc) as seqnum
from t
) t
where seqnum = 1;
With the right indexes, the correlated subquery often performs better.
Only because it was not mentioned.
Yet another option is the WITH TIES clause.
To be clear, the approach by Gordon and Barbaros would be a nudge more performant, but this technique does not require or generate an extra column.
Select Top 1 with ties *
From YourTable
Order By row_number() over (partition by month order by price desc)
With not exists:
select t.*
from tablename t
where not exists (
select 1 from tablename
where month = t.month and price > t.price
)
or:
select t.*
from tablename inner join (
select month, max(price) as price
from tablename
group By month
) g on g.month = t.month and g.price = t.price

SQL query to get recent items

I have a sql table
id item date
A apple 2017-09-17
A banana 2017-08-10
A orange 2017-10-01
B banana 2015-06-17
B apple 2014-06-18
How do I write a sql query, so that for each id I get the two most recent items based on date. ex:
id recent second_recent
a orange apple
b banana apple
You can use row_number() and conditional aggregation:
select id,
max(case when seqnum = 1 then item end) as most_recent,
max(case when seqnum = 2 then item end) as most_recent_but_one,
from (select t.*,
row_number() over (partition by id order by date desc) as seqnum
from t
) t
group by id;
Like said on:
SQL: Group by minimum value in one field while selecting distinct rows
You must use A group By to get min
SELECT mt.*,
FROM MyTable mt INNER JOIN
(
SELECT item AS recent, MIN(date) MinDate, ID
FROM MyTable
GROUP BY ID
) t ON mt.ID = t.ID AND mt.date = t.MinDate
I think you can do the same with a order by to get two value instead of one
You can use Pivot table
SELECT first_column AS <first_column_alias>,
[pivot_value1], [pivot_value2], ... [pivot_value_n]
FROM
(<source_table>) AS <source_table_alias>
PIVOT
(
aggregate_function(<aggregate_column>)
FOR <pivot_column> IN ([pivot_value1], [pivot_value2], ... [pivot_value_n])
) AS <pivot_table_alias>;
Learn More with example here
Example

Join two queries from the same table - SELECT DISTINCT?

I have two tables linked by an AUTO_KEY field, from one table I'm retrieving the number (id), from the other I get several statuses by number(id), each status has a date associated to it.
I need to restrict the results only to the maximum/latest date for all numbers(ids) and the corresponding status
SELECT
OPERATION.NUMBER,
STATUS.STATUS,
Max(STATUS.DATE)
FROM
STATUS,
OPERATION
WHERE
OPERATION.AUTO_KEY = STATUS.AUTO_KEY
From here
Number Status Date
-----------------------------
1 A 10/20/13
1 B 10/15/13
2 A 10/10/13
2 AX 10/05/13
2 AD 10/03/13
3 DD 10/03/13
The outcome should be
Number Status Date
-----------------------------
1 A 10/20/13
2 A 10/10/13
3 DD 10/03/13
Thanks in advance
You can use a CTE with ROW_NUMBER() function. Also Please use a Table JOIN instead FROM STATUS, OPERATION
;With CTE AS (
SELECT O.NUMBER, S.STATUS, S.DATE,
ROW_NUMBER() OVER (ORDER BY S.DATE DESC) RN
FROM STATUS S JOIN OPERATION O
ON O.AUTO_KEY = S.AUTO_KEY
)
SELECT NUMBER, STATUS, DATE
FROM CTE
WHERE RN = 1
ORDER BY NUMBER
SELECT OPERATION.CNUMBER,
STATUS.STATUS,
STATUS.CDATE
FROM STATUS,
OPERATION
WHERE OPERATION.AUTO_KEY = STATUS.AUTO_KEY
AND STATUS.CDATE = (
SELECT MAX(STATUS.CDATE) MAX_DATE
FROM STATUS,
OPERATION
WHERE OPERATION.AUTO_KEY = STATUS.AUTO_KEY
GROUP BY OPERATION.CNUMBER )

Select newest records that have distinct Name column

I did search around and I found this
SQL selecting rows by most recent date with two unique columns
Which is so close to what I want but I can't seem to make it work.
I get an error Column 'ID' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
I want the newest row by date for each Distinct Name
Select ID,Name,Price,Date
From table
Group By Name
Order By Date ASC
Here is an example of what I want
Table
ID
Name
Price
Date
0
A
10
2012-05-03
1
B
9
2012-05-02
2
A
8
2012-05-04
3
C
10
2012-05-03
4
B
8
2012-05-01
desired result
ID
Name
Price
Date
2
A
8
2012-05-04
3
C
10
2012-05-03
1
B
9
2012-05-02
I am using Microsoft SQL Server 2008
Select ID,Name, Price,Date
From temp t1
where date = (select max(date) from temp where t1.name =temp.name)
order by date desc
Here is a SQL Fiddle with a demo of the above
Or as Conrad points out you can use an INNER JOIN (another SQL Fiddle with a demo) :
SELECT t1.ID, t1.Name, t1.Price, t1.Date
FROM temp t1
INNER JOIN
(
SELECT Max(date) date, name
FROM temp
GROUP BY name
) AS t2
ON t1.name = t2.name
AND t1.date = t2.date
ORDER BY date DESC
There a couple ways to do this. This one uses ROW_NUMBER. Just partition by Name and then order by what you want to put the values you want in the first position.
WITH cte
AS (SELECT Row_number() OVER (partition BY NAME ORDER BY date DESC) RN,
id,
name,
price,
date
FROM table1)
SELECT id,
name,
price,
date
FROM cte
WHERE rn = 1
DEMO
Note you should probably add ID (partition BY NAME ORDER BY date DESC, ID DESC) in your actual query as a tie-breaker for date
select * from (
Select
ID, Name, Price, Date,
Rank() over (partition by Name order by Date) RankOrder
From table
) T
where RankOrder = 1
I have found another memory efficient way (but probably crude way)that has worked for me in postgress. Order the query by the date desc, then select the first record of each distinct field.
SELECT distinct on (Name) ID, Price, Date from
table
order by Date desc
Use Distinct instead of Group By
Select Distinct ID,Name,Price,Date
From table
Order By Date ASC
http://technet.microsoft.com/en-us/library/ms187831.aspx