How to query latest records in SQL Server - sql

I've tried to to use similar asks but still not able to get my desired result. Here is three sample records.
create table #temps
(
airport varchar(10),
country varchar(10),
plane varchar(10),
id int,
flight_date datetime
)
insert into #temps
values ('IAD', 'USA', 'a777', '195', ' 7/26/2022 11:39:00 AM')
insert into #temps
values ('IAD', 'USA', 'a777', '195', ' 8/12/2022 9:51:00 AM')
insert into #temps
values ('BOS', 'USA', 'a777', '195', ' 8/12/2022 9:51:00 AM')
I tried to retrieve the latest record which is from BOS airport (discard the impossible of the same flight dates occurred from different airports)
I used the ROW_NUMBER such as below and and wanted to return the max rank = 3.
SELECT DISTINCT
a.airport, a.country, a.flight_date, a.plane, id,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY flight_date ASC) AS Ct
FROM
#temps a
I also tried the max such as
SELECT A.airport, A.id, A.flight_date, A.country
FROM #temps A
INNER JOIN (SELECT id, MAX(flight_date) as MAX_FLIGHT_DATE
FROM #temps
GROUP BY id) B ON (A.flight_date = B.MAX_FLIGHT_DATE)
Is there a better technique that can return the record from BOS airport?
Thanks!
joe

You could use ORDER by.
SELECT TOP(3) airport,
country,
plane,
id,
flight_date
FROM #temps
ORDER BY flight_date DESC;

Related

SQL-find the ratings with the max complete_date with group by

Please run the DDL and DML on sqlfiddle. I am trying to come up with a query to find the ratings of the FID that has the max complete_date
DDL:
create table crr (rating varchar(255), FID int, complete_date varchar(255));
DML:
insert into crr values ('low', 182, '2021/11/1'),('medium', 182,'2022/6/14'), ('medium', 369,'2021/9/1')
, ('medium', 369,'2021/11/9'), ('medium', 429,'2021/4/5'), ('medium', 429,'2021/4/6'),('high', 429,'2022/12/5');
my query is:
Select c.fid, rating, c.complete_date
From crr c
Inner Join (
Select fid, Max(complete_date)as d
From crr
Group By fid)A;
On c.fid=A.fid and c.complete_date=d;
It is not returning what I wanted.
Ideal output would be:
rating FID complete_date
medium 182 2022/6/14
medium 369 2021/11/9
high 429 2022/12/5
It should be easy-peasy, please advise.
Is that what you are looking for?
select * from crr a
where complete_date = (select max(complete_date) from crr b where b.fid=a.fid)
order by fid
I changed completed_date to date, with varchar I was having different results
create table crr (rating varchar(255), FID int, complete_date date);
insert into crr values ('low', 182, '2021/11/1'),('medium', 182,'2022/6/14'), ('medium', 369,'2021/9/1')
, ('medium', 369,'2021/11/9'), ('medium', 429,'2021/4/5'), ('medium', 429,'2021/4/6'),('high', 429,'2022/12/5');
Select rating, c.fid, c.complete_date
From crr c
Inner Join (
Select fid, Max(complete_date) as d
From crr
Group By fid) as A On c.fid=A.fid and c.complete_date=A.d;
Date is a string, then sorting will be in lexicographic order
Come to think of it.
This is what I came up with
select rating, fid, complete_date from (
select *, row_number() over(partition by FID order by complete_date desc)as n
from crr)A
where A.n=1

Select the newest record

I would like to run a select statement that runs and select only the newest record by Recored_timestampe field for the keys teacher_id and student_id. So any time, it runs it needs to provide only one record. how could I do it, please? The output could be without the field Recored_timestampe. Thanks
Using the window function,partitioned by teacher_id and student_id and sorting it by recorded_timestamp will give you the desired result.
select * from(select teacher_id,student_id,teacher_name,comment ,recorded_timestamp, row_number() over(partition by teacher_id,student_id order by recorded_timestamp desc)as rownum from temp0607)out1 where rownum=1
Also you may have to look at the way recorded_timestamp is stored. If it is stored as string, you can convert it into timestamp using from_unixtime(unix_timestamp(recorded_timestamp,'dd/MM/yyyy HH:mm'),'dd/MM/yyyy HH:mm')
First, arrange the record by datetime
SELECT *,RANK() OVER (PARTITION BY student_id ORDER BY Recored_timestamp desc) as ranking
FROM #temp
Then, if you want to know the newest record with student_id which is not null, then you can use OUTER APPLY to add a column which is non-NULL student_id.
OUTER APPLY (SELECT student_id
FROM #temp
WHERE #temp.teacher_id = ranktable.teacher_id
AND student_id IS NOT NULL
) AS jointable
Here is an example:
Create Table #temp
(
teacher_id int
,student_id int
,teacher_name varchar(40)
,comment varchar(100)
,Recored_timestamp datetime
)
INSERT INTO #temp
VALUES
(449,111,'lucy','Could be better','2021-05-04 07:00:00.000')
,(449,null,'lucy','smily','2021-05-11 07:00:00.000')
,(449,111,'lucy','not listening','2021-05-08 07:00:00.000')
,(448,null,'Toni','Good','2021-06-04 09:00:00.000')
,(448,222,'Toni','not doing as expected','2021-06-04 08:00:00.000')
SELECT DISTINCT teacher_id,
jointable.student_id,
teacher_name,
comment,
Recored_timestamp,
ranking
FROM
(
SELECT *,RANK() OVER (PARTITION BY teacher_id ORDER BY Recored_timestamp DESC) AS ranking
FROM #temp
) AS ranktable
OUTER APPLY (SELECT student_id
FROM #temp
WHERE #temp.teacher_id = ranktable.teacher_id
AND student_id IS NOT NULL
) AS jointable
WHERE ranking = 1 --only newest record will be extracted
Drop table #temp
You can base from this query to get the newest data.
SELECT TOP 1 * FROM tablename T1
INNER JOIN(SELECT teacher_id, Max(Recored_timestamp) as MaxDate from tablename GROUP BY teacher_id) T2 ON T2.teacher_id = T1.teacher_id AND T1.Recored_timestamp = T2.MaxDate

display latest bill month

I have t_cust table and I want to display customer's latest bill month and bill amount.
I have written query but for large data it will take much time.Is there any simple
logic to find latest bill month?
create table t_cust
(
cust_id varchar2(3),
b_year varchar2(4),
b_month varchar2(2),
b_amount number
);
insert into t_cust values('ABC','2015','11',100);
insert into t_cust values('ABC','2015','12',200);
insert into t_cust values('ABC','2016','01',300);
insert into t_cust values('XYZ','2016','01',1000);
insert into t_cust values('XYZ','2016','02',2000);
insert into t_cust values('XYZ','2016','03',3000);
commit;
select cust_id,substr(to_date(b_year*100+b_month,'YYYYMM'),4)latest_bill_mth,b_amount bill_amount
from t_cust
where (cust_id,b_year*100+b_month) in (
select cust_id,max(b_year*100+b_month)
from t_cust
group by cust_id
);
Looks like Oracle, so simply use a ROW_NUMBER/RANK:
select ...
from
(
select ...
,row_number()
over (partition by t_cust
order by year desc, month desc) as rn
) dt
where rn = 1

Oracle - Calculating time differences

Let's say I have following data:
Create Table Pm_Test (
Ticket_id Number,
Department_From varchar2(100),
Department_To varchar2(100),
Routing_Date Date
);
Insert Into Pm_Test Values (1,'A','B',To_Date('20140101120005','yyyymmddhh24miss'));
Insert Into Pm_Test Values (1,'B','C',To_Date('20140101130004','yyyymmddhh24miss'));
Insert Into Pm_Test Values (1,'C','D',To_Date('20140101130004','yyyymmddhh24miss'));
Insert Into Pm_Test Values (1,'D','E',To_Date('20140201150004','yyyymmddhh24miss'));
Insert Into Pm_Test Values (2,'A','B',To_Date('20140102120005','yyyymmddhh24miss'));
Insert Into Pm_Test Values (3,'D','B',To_Date('20140102120005','yyyymmddhh24miss'));
Insert Into Pm_Test Values (3,'B','A',To_Date('20140102170005','yyyymmddhh24miss'));
For the following requirements I already added two virtual columns, I think they might be necessary:
Select t.*,
Count(Ticket_id) Over (Partition By Ticket_id Order By Ticket_id) Cnt_Id,
Row_Number() Over (Partition By Ticket_id Order By Ticket_id ) row_number
From Pm_Test t;
1) I want to measure how long each ticket stayed in a department (routing_date of successor_department - routing_date of predecessor department) by adding the column PROCESSING_TIME:
2) I want to measure the total processing time by adding the column TOTAL_PROCESSING_TIME:
What SQL statements would be necessary to do so?
Thank you very much in advance!
To solve your problem, the way you described, the following sql should get you there. One thing to keep in mind, this data model doesn't seem the most efficient to capture processing times, if that's its true intent as the first department to get the ticket isn't measured.
select dept.ticket_id, department_from, department_to, routing_date, dept_processing_time, total_ticket_processing_time
from
(select ticket_id, max(routing_date) - min(routing_date) total_ticket_processing_time
from pm_test
group by ticket_id) total
join
(select ticket_id, department_from, department_to, routing_date,
coalesce(routing_date - lag(routing_date) over (partition by ticket_id order by routing_date), 0) dept_processing_time
from pm_test) dept
on (total.ticket_id = dept.ticket_id);
This query produces desired output. Analytic functions max(), min() and lag() used for calculations.
Results are in hours, like in your question.
SQLFiddle
select t.ticket_id, t.department_from, t.department_to,
to_char(t.routing_date, 'mm.dd.yy hh24:mi:ss') rd,
count(ticket_id) over (partition by ticket_id) cnt_id,
row_number() over (partition by ticket_id order by t.routing_date ) rn,
round(24 * (t.routing_date-
nvl(lag(t.routing_date) over (partition by ticket_id
order by t.routing_date), routing_date) ) , 8) dept_time,
round(24 * (max(t.routing_date) over (partition by ticket_id)
- min(t.routing_date) over (partition by ticket_id)), 8) total_time
from pm_test t

select the latest result based on DateTime field

I have a simple table with only 4 fields.
http://sqlfiddle.com/#!3/06d7d/1
CREATE TABLE Assessment (
id INTEGER IDENTITY(1,1) PRIMARY KEY,
personId INTEGER NOT NULL,
dateTaken DATETIME,
outcomeLevel VARCHAR(2)
)
INSERT INTO Assessment (personId, dateTaken, outcomeLevel)
VALUES (1, '2014-04-01', 'L1')
INSERT INTO Assessment (personId, dateTaken, outcomeLevel)
VALUES (1, '2014-04-05', 'L2')
INSERT INTO Assessment (personId, dateTaken, outcomeLevel)
VALUES (2, '2014-04-03', 'E3')
INSERT INTO Assessment (personId, dateTaken, outcomeLevel)
VALUES (2, '2014-04-07', 'L1')
I am trying to select for each "personId" their latest assessment result based on the dateTaken.
So my desired output for the following data would be.
[personId, outcomeLevel]
[1, L2]
[2, L1]
Thanks,
Danny
Try this:
;with cte as
(select personId pid, max(dateTaken) maxdate
from assessment
group by personId)
select personId, outcomeLevel
from assessment a
inner join cte c on a.personId = c.pid
where c.maxdate = a.dateTaken
order by a.personId
;with Cte as (Select personId,outcomeLevel, C= ROW_NUMBER()
over(PARTITION By personId Order By dateTaken desc)
From #Assessment
)
Select * from cte where C=1
Sample here
SELECT asst.personId,
asst.outcomeLevel
FROM dbo.Assessment asst
WHERE asst.dateTaken=(SELECT MAX(ast.dateTaken)
FROM assessment ast
WHERE asst.personid=ast.personId)
ORDER BY asst.personId
Result will be like this
personId outcomeLevel
1 L2
2 L1
Here is a possible solution using common table expression:
WITH cte AS (
SELECT
ROW_NUMBER() OVER (PARTITION BY personId ORDER BY dateTaken DESC) AS rn
, personId
, outcomeLevel
FROM
[dbo].[Assessment]
)
SELECT
personId
, outcomeLevel
FROM
cte
WHERE
rn = 1
About CTEs
A common table expression (CTE) can be thought of as a temporary result set that is defined within the execution scope of a single SELECT, INSERT, UPDATE, DELETE, or CREATE VIEW statement. A CTE is similar to a derived table in that it is not stored as an object and lasts only for the duration of the query. Unlike a derived table, a CTE can be self-referencing and can be referenced multiple times in the same query. From MSDN: Using Common Table Expressions
try this:
SELECT a.personId, a.outcomeLevel
FROM Assessment a
INNER JOIN
(
SELECT max(dateTaken) as datetaken1, personId
FROM Assessment
GROUP BY personId ) b
ON a.dateTaken = b.datetaken1
demo: http://sqlfiddle.com/#!3/06d7d/9
Idea is to first derive a table with the max dates per person and then join that with the original table on the date field so you can get the outcome level for this maxed date...
This should work perfectly without cte :
SELECT [Table4].[personId], [Table4].[outcomeLevel]
FROM (
SELECT [Table1].[personId]
FROM [Assessment] AS [Table1]
GROUP BY [Table1].[personId]
) AS [Table2]
CROSS APPLY (
SELECT TOP (1) [Table3].[personId], [Table3].[outcomeLevel], [Table3].[dateTaken]
FROM [Assessment] AS [Table3]
WHERE [Table2].[personId] = [Table3].[personId]
ORDER BY [Table3].[dateTaken] DESC
) AS [Table4]
ORDER BY [Table4].[dateTaken] DESC