max with distinct in sql - sql

I have a table with rows/data in the following structure
picture
I want a query that results in the red line(max credit no)
I have tried these:
SELECT employee no, MAX(credit no)
FROM mytable
GROUP BY employee no
SELECT distinct employee no, MAX(credit no)
FROM mytable
GROUP BY employee no
but it doesn't give me the red line records

You can use correlated subquery :
select mt.*
from mytable mt
where mt.creditno = (select max(mt1.creditno)
from mytable mt1
where mt1.employeeno = mt.employeeno
);

You sould use group by and order by clouse. if you want to just top 2 employee_no, write to select top 2
select employee_no, max(credit_no) as max_credit_no from yourtable group by employee_no order by max_credit_no desc
select top 2, employee_no, max(credit_no) as max_credit_no from yourtable group by employee_no order by max_credit_no desc

if I understand correctly, I would use the line number to sort the values in descending order then select the lines.
CREATE TABLE #data
(
employee_no int,
credit_no int,
stat nvarchar(3)
)
INSERT INTO #data
(employee_no, credit_no, stat)
VALUES
(100022, 244, 'ret'),
(100022, 245, 'emp'),
(100023, 244, 'vac'),
(100023, 245, 'ret'),
(100023, 246, 'emp')*/
And select:
select *
from (
select employee_no,
credit_no,
stat,
ROW_NUMBER() over (partition by employee_no order by credit_no desc) id
from #data
)x
where id = 1
And result:
https://dbfiddle.uk/?rdbms=sqlserver_2016&fiddle=2b97f6e553231a6a9524b143e730f323

Related

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

Sql select distinct row by a columns highest value

I am having an issue trying to select one row per city name. This is the following collection I am getting:
This is my query so far:
select pl.PlaceId,
pl.Name,
pop.NumberOfPeople,
pop.Year
from dbo.Places pl
inner join dbo.Populations pop
on pop.PlaceId = pl.PlaceId
where pop.NumberOfPeople >= 1000
and pop.NumberOfPeople <= 99999
I am trying to get it to where it only selects a city one time, but uses the most recent date. So in the above picture, I would only see Abbeville for 2016 and not 2015. I believe I need to do either a group by or do a sub query to flatten the results. If anybody has any advice on how I can handle this, it will be greatly appreciated.
Assuming you are using SQLSERVER,you can use Rownumber
;with cte
as
(select pl.PlaceId,
pl.Name,
pop.NumberOfPeople,
pop.Year,
row_number() over(partition by pl.Name order by year desc) as rownum
from dbo.Places pl
inner join dbo.Populations pop
on pop.PlaceId = pl.PlaceId
where pop.NumberOfPeople >= 1000
and pop.NumberOfPeople <= 99999
)
select * from cte where rownum=1
The following query serves the purpose.
CREATE TABLE #TEMP_TEST
(
PlaceId INT,
Name VARCHAR(50),
NumberOfPeople INT,
YEAR INT
)
INSERT INTO #TEMP_TEST
SELECT 1,'Abbeville',2603,2016
UNION
SELECT 5,'Alabester',32948,2016
UNION
SELECT 9,'Aubum',63118,2016
UNION
SELECT 1,'Abbeville',2402,2015
UNION
SELECT 5,'Alabester',67902,2017
SELECT PlaceId, Name, NumberOfPeople, YEAR FROM
(
SELECT ROW_NUMBER() OVER (PARTITION BY PlaceId ORDER BY YEAR DESC) RNO,
PlaceId, Name, NumberOfPeople, YEAR
FROM #TEMP_TEST
)T
WHERE RNO = 1
DROP TABLE #TEMP_TEST

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

SQL select latest record of particular student with particular status

Please help me to select latest record of each student with status=1. I have a table called stdData and columns
Student ID FDate Status
12 2014-03-12 1
12 2014-03-15 1
13 2014-02-03 1
13 2014-02-04 0
13 2014-02-05 1
How can I select latest record of each student with status=1?
You need to use group by
select student_id, max(date)
from table_name
where status=1
group by student_id;
fiddle
if you are using sql server then try this
Select top(1) * from StudentTable where status =1 order by student_id desc
In this query it is clear that status = 1 there for i add it in my select, like this:
Select Student_ID ,max(Date) Date, 1 status From table1
where status = 1 Group by Student_ID;
SQL Fiddle
In Sqlserver
Create table Student(
ID int identity(1,1) primary key not null,
S_Date datetime,
Status bit
)
insert into Student values ('2014-03-11',1)
insert into Student values ('2014-03-12',0)
insert into Student values ('2014-03-13',1)
insert into Student values ('2014-03-14',0)
insert into Student values ('2014-03-15',1)
select top 1 * from Student where Status=1 Order By S_Date Desc
You can use ROW_NUMBER function to achieve this:
SELECT Student_ID, Date , Status
FROM
(
SELECT ROW_NUMBER() OVER (PARTITION BY Student_ID ORDER BY Date DESC) AS rn, Student_ID, Date , Status
FROM your_table
WHERE Status = 1
) tab
WHERE tab.rn = 1
try this !
;with cte as
(
select *,rn=row_number() over(partition by Student_Id order by Date desc) from #t
)
select * from cte where rn=1 and status=1
SEE DEMO
try this !
SELECT LAST(column_name) FROM table_name;

How to reverse the table that comes from SQL query which already includes ORDER BY

Here is my query:
SELECT TOP 8 id, rssi1, date
FROM history
WHERE (siteName = 'CCL03412')
ORDER BY id DESC
This the result:
How can I reverse this table based on date (Column2) by using SQL?
You can use the first query to get the matching ids, and use them as part of an IN clause:
SELECT id, rssi1, date
FROM history
WHERE id IN
(
SELECT TOP 8 id
FROM history
WHERE (siteName = 'CCL03412')
ORDER BY id DESC
)
ORDER BY date ASC
You could simply use a sub-query. If you apply a TOP clause the nested ORDER BY is allowed:
SELECT X.* FROM(
SELECT TOP 8 id, Column1, Column2
FROM dbo.History
WHERE (siteName = 'CCL03412')
ORDER BY id DESC) X
ORDER BY Column2
Demo
The SELECT query of a subquery is always enclosed in parentheses. It
cannot include a COMPUTE or FOR BROWSE clause, and may only include an
ORDER BY clause when a TOP clause is also specified.
Subquery Fundamentals
try the below :
select * from (SELECT TOP 8 id, rssi1, date
FROM history
WHERE (siteName = 'CCL03412')
ORDER BY id DESC ) aa order by aa.date DESC
didn't run it, but i think it should go well
WITH cte AS
(
SELECT id, rssi1, date, RANK() OVER (ORDER BY ID DESC) AS Rank
FROM history
WHERE (siteName = 'CCL03412')
)
SELECT id, rssi1, date
FROM cte
WHERE Rank <= 8
ORDER BY Date DESC
I have not run this but i think it will work. Execute and let me know if you face error
select id, rssi1, date from (SELECT TOP 8 id, rssi1, date
FROM history
WHERE (siteName = 'CCL03412')
ORDER BY id DESC) order by date ;