SQL Max Value of Column to choose which row is selected - sql

I'm having a problem with selecting a single row when there are multiple entries for one "callid"
In this case there are two rows being selected:
Assignee maxTime
Jim Smith 11:31:05
James Smith 17:50:16
I want to only select a single row that has the greatest time.
Output I want:
Assignee maxTime
James Smith 17:50:16
This is my code:
select Assignee, MAX(TimeResolv) as maxTime
from heat8..asgnmnt
where callid ='00539265'
and GroupName like '%cs%'
Group by Assignee
Help would be appreciated.

You can use TOP :
SELECT TOP 1 *
FROM heat8..asgnmntt t
ORDER BY t.timeResolv DESC
Or less efficient with NOT EXISTS():
SELECT * FROM heat8..asgnmntt t
WHERE NOT EXISTS(SELECT 1 FROM heat8..asgnmnt s
WHERE s.timeResolv > t.timeResolv)
Or with window function ROW_NUMBER() :
SELECT s.Assignee, s.TimeResolv
FROM (
SELECT t.*,
ROW_NUMBER() OVER(ORDER BY t.timeResolv) as rnk
FROM heat8..asgnmntt t) s
WHERE s.rnk = 1
ROW_NUMBER() is also good to do it with one query for results per group.

You can use a subquery. Your subquery will look exactly like your current query, but you will need to select top 1 from it.
select TOP 1 Assignee, (TimeResolv) as maxTime
FROM (
select Assignee, MAX(TimeResolv) as maxTime
from heat8..asgnmnt
where callid ='00539265'
and GroupName like '%cs%'
Group by Assignee
)
ORDER BY TimeResolv DESC
EDIT: no need for subquery, but if you want to use the same code you did above for easy readability or it just makes sense to you. You can continue to use it with this method.

Related

Find the second largest value with Groupings

In SQL Server, I am attempting to pull the second latest NOTE_ENTRY_DT_TIME (items highlighted in screenshot). With the query written below it still pulls the latest date (I believe it's because of the grouping but the grouping is required to join later). What is the best method to achieve this?
SELECT
hop.ACCOUNT_ID,
MAX(hop.NOTE_ENTRY_DT_TIME) AS latest_noteid
FROM
NOTES hop
WHERE
hop.GEN_YN IS NULL
AND hop.NOTE_ENTRY_DT_TIME < (SELECT MAX(hope.NOTE_ENTRY_DT_TIME)
FROM NOTES hope
WHERE hop.GEN_YN IS NULL)
GROUP BY
hop.ACCOUNT_ID
Data sample in the table:
One of the "easier" ways to get the Nth row in a group is to use a CTE and ROW_NUMBER:
WITH CTE AS(
SELECT Account_ID,
Note_Entry_Dt_Time,
ROW_NUMBER() OVER (PARTITION BY AccountID ORDER BY Note_Entry_Dt_Time DESC) AS RN
FROM dbo.YourTable)
SELECT Account_ID,
Note_Entry_Dt_Time
FROM CTE
WHERE RN = 2;
Of course, if an ACCOUNT_ID only has 1 row, then it will not be returned in the result set.
The OP's statement "The row will not always be 2." from the comments conflicts with their statement "I am attempting to pull the second latest NOTE_ENTRY_DT_TIME" in the question. At a best guess, this means that the OP has rows with the same date, that could be the "latest" date. If so, then would simply need to replace ROW_NUMBER with DENSE_RANK. Their sampple data, however, doesn't suggest this is the case.
You can use window functions:
select *
from (
select
n.*,
row_number() over(partition by account_id order by note_entry_dt_time desc) rn
from notes n
) t
where rn = 2

How to select duplicates by first order of appearance

I am looking to select unique values from a SQL database but I want to make sure that I am selecting only the first duplicate in order of appearance (in my case - date in the hospital, intime col)
You can see the code below.
I am trying to take only the IDs of the first time the patients were hospitalized which correspond to the "intime" col.
I have no absolute way to check that by ordering as I did and by using groupby, SQL will in fact return the id in the same order.
Thank you very much.
WITH ccupatients AS
(SELECT HADM_ID
FROM `physionet-data.mimiciii_clinical.icustays` i
WHERE first_careunit = 'CCU'
ORDER BY intime)
SELECT hadm_id
FROM ccupatients
GROUP BY hadm_id
Use ROW_NUMBER() if your RDBMS supports it: this works by ranking records by increasing intime within groups of records having the same ham_id, and then filtering in the outer query on the top record per group:
SELECT hadm_id
FROM (
SELECT hadm_id, ROW_NUMBER() OVER(PARTITION BY hadm_id ORDER BY intime) rn
FROM `physionet-data.mimiciii_clinical`.icustays
WHERE first_careunit = 'CCU'
) x
WHERE rn = 1
If you RDBMS does not support window functions such as ROW_NUMBER(), another option is to use a NOT EXISTS condition with a correlated subquery:
SELECT hadm_id
FROM `physionet-data.mimiciii_clinical`.icustays i
WHERE
first_careunit = 'CCU'
AND NOT EXISTS (
SELECT 1
FROM `physionet-data.mimiciii_clinical`.icustays i1
WHERE
i1.first_careunit = 'CCU'
AND i1.hadm_id = i.hadm_id
AND i1.intime < i.intime
)

how to get latest date column records when result should be filtered with unique column name in sql?

I have table as below:
I want write a sql query to get output as below:
the query should select all the records from the table but, when multiple records have same Id column value then it should take only one record having latest Date.
E.g., Here Rudolf id 1211 is present three times in input---in output only one Rudolf record having date 06-12-2010 is selected. same thing with James.
I tried to write a query but it was not succssful. So, please help me to form a query string in sql.
Thanks in advance
You can partition your data over Date Desc and get the first row of each partition
SELECT A.Id, A.Name, A.Place, A.Date FROM (
SELECT
*,
ROW_NUMBER() OVER (PARTITION BY Id ORDER BY Date DESC) AS rn
FROM [Table]
) A WHERE A.rn = 1
you can use WITH TIES
select top 1 PERCENT WITH TIES * from t
order by (row_number() over(partition by id order by date desc))
https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=280b7412b5c0c04c208f2914b44c7ce3
As i can see from your example, duplicate rows differ only in Date. If it's a case, then simple GROUP BY with MAX aggregate function will do the job for you.
SELECT Id, Name, Place, MAX(Date)
FROM [TABLE_NAME]
GROUP BY Id, Name, Place
Here is working example: http://sqlfiddle.com/#!18/7025e/2

How can I SELECT additional columns with a TSQL query using GROUP BY

I have a view (that is a union of several tables) and I need to filter out duplicates. The table looks like this:
id first last logo email entered
1 joe smith i.jpg e#m.c 2014-01-27
2 jim smith b.jpg e#j.c 2014-01-27
3 bob smith z.jpg b#b.c 2014-01-27
9 joeseph smith q.gif e#m.c 2014-01-20
I want to do something like this, but I can't seem to get a valid syntax for it:
SELECT
email, MAX(entered), first, last -- such that first and last come from the same row as the MAX(entered)
FROM
my_view
GROUP BY
email
Since your names are not the same on the duplicate email rows, you must use the row_number() function instead:
select email, entered, first, last
from (
select *, row_number() over (partition by email order by entered desc) rn
from my_view
) x
where rn = 1
You need a subquery because row_number() is not allowed in the where clause.
You want to use row_number():
SELECT email, entered, first, last
FROM (select v.*, row_number() over (partition by email order by entered desc) as seqnum
from my_view v
) v
WHERE seqnum = 1;
row_number() is a window function that assigns sequential numbers to groups of rows. The groups are defined by the partition by clause. In this case, everything with the same email is in the same group. The first row is given a value 1; the ordering is based on the order by clause.
The outer query select the first one, which has the largest entered date.

How do I use ROW_NUMBER()?

I want to use the ROW_NUMBER() to get...
To get the max(ROW_NUMBER()) --> Or i guess this would also be the count of all rows
I tried doing:
SELECT max(ROW_NUMBER() OVER(ORDER BY UserId)) FROM Users
but it didn't seem to work...
To get ROW_NUMBER() using a given piece of information, ie. if I have a name and I want to know what row the name came from.
I assume it would be something similar to what I tried for #1
SELECT ROW_NUMBER() OVER(ORDER BY UserId) From Users WHERE UserName='Joe'
but this didn't work either...
Any Ideas?
For the first question, why not just use?
SELECT COUNT(*) FROM myTable
to get the count.
And for the second question, the primary key of the row is what should be used to identify a particular row. Don't try and use the row number for that.
If you returned Row_Number() in your main query,
SELECT ROW_NUMBER() OVER (Order by Id) AS RowNumber, Field1, Field2, Field3
FROM User
Then when you want to go 5 rows back then you can take the current row number and use the following query to determine the row with currentrow -5
SELECT us.Id
FROM (SELECT ROW_NUMBER() OVER (ORDER BY id) AS Row, Id
FROM User ) us
WHERE Row = CurrentRow - 5
Though I agree with others that you could use count() to get the total number of rows, here is how you can use the row_count():
To get the total no of rows:
with temp as (
select row_number() over (order by id) as rownum
from table_name
)
select max(rownum) from temp
To get the row numbers where name is Matt:
with temp as (
select name, row_number() over (order by id) as rownum
from table_name
)
select rownum from temp where name like 'Matt'
You can further use min(rownum) or max(rownum) to get the first or last row for Matt respectively.
These were very simple implementations of row_number(). You can use it for more complex grouping. Check out my response on Advanced grouping without using a sub query
If you need to return the table's total row count, you can use an alternative way to the SELECT COUNT(*) statement.
Because SELECT COUNT(*) makes a full table scan to return the row count, it can take very long time for a large table. You can use the sysindexes system table instead in this case. There is a ROWS column that contains the total row count for each table in your database. You can use the following select statement:
SELECT rows FROM sysindexes WHERE id = OBJECT_ID('table_name') AND indid < 2
This will drastically reduce the time your query takes.
You can use this for get first record where has clause
SELECT TOP(1) * , ROW_NUMBER() OVER(ORDER BY UserId) AS rownum
FROM Users
WHERE UserName = 'Joe'
ORDER BY rownum ASC
ROW_NUMBER() returns a unique number for each row starting with 1. You can easily use this by simply writing:
ROW_NUMBER() OVER (ORDER BY 'Column_Name' DESC) as ROW_NUMBER
May not be related to the question here. But I found it could be useful when using ROW_NUMBER -
SELECT *,
ROW_NUMBER() OVER (ORDER BY (SELECT 100)) AS Any_ID
FROM #Any_Table
select
Ml.Hid,
ml.blockid,
row_number() over (partition by ml.blockid order by Ml.Hid desc) as rownumber,
H.HNAME
from MIT_LeadBechmarkHamletwise ML
join [MT.HAMLE] h on ML.Hid=h.HID
SELECT num, UserName FROM
(SELECT UserName, ROW_NUMBER() OVER(ORDER BY UserId) AS num
From Users) AS numbered
WHERE UserName='Joe'
You can use Row_Number for limit query result.
Example:
SELECT * FROM (
select row_number() OVER (order by createtime desc) AS ROWINDEX,*
from TABLENAME ) TB
WHERE TB.ROWINDEX between 0 and 10
--
With above query, I will get PAGE 1 of results from TABLENAME.
If you absolutely want to use ROW_NUMBER for this (instead of count(*)) you can always use:
SELECT TOP 1 ROW_NUMBER() OVER (ORDER BY Id)
FROM USERS
ORDER BY ROW_NUMBER() OVER (ORDER BY Id) DESC
Need to create virtual table by using WITH table AS, which is mention in given Query.
By using this virtual table, you can perform CRUD operation w.r.t row_number.
QUERY:
WITH table AS
-
(SELECT row_number() OVER(ORDER BY UserId) rn, * FROM Users)
-
SELECT * FROM table WHERE UserName='Joe'
-
You can use INSERT, UPDATE or DELETE in last sentence by in spite of SELECT.
SQL Row_Number() function is to sort and assign an order number to data rows in related record set. So it is used to number rows, for example to identify the top 10 rows which have the highest order amount or identify the order of each customer which is the highest amount, etc.
If you want to sort the dataset and number each row by seperating them into categories we use Row_Number() with Partition By clause. For example, sorting orders of each customer within itself where the dataset contains all orders, etc.
SELECT
SalesOrderNumber,
CustomerId,
SubTotal,
ROW_NUMBER() OVER (PARTITION BY CustomerId ORDER BY SubTotal DESC) rn
FROM Sales.SalesOrderHeader
But as I understand you want to calculate the number of rows of grouped by a column. To visualize the requirement, if you want to see the count of all orders of the related customer as a seperate column besides order info, you can use COUNT() aggregation function with Partition By clause
For example,
SELECT
SalesOrderNumber,
CustomerId,
COUNT(*) OVER (PARTITION BY CustomerId) CustomerOrderCount
FROM Sales.SalesOrderHeader
This query:
SELECT ROW_NUMBER() OVER(ORDER BY UserId) From Users WHERE UserName='Joe'
will return all rows where the UserName is 'Joe' UNLESS you have no UserName='Joe'
They will be listed in order of UserID and the row_number field will start with 1 and increment however many rows contain UserName='Joe'
If it does not work for you then your WHERE command has an issue OR there is no UserID in the table. Check spelling for both fields UserID and UserName.