Finding row with max values in two groups - sql

I use SQL Server 2012,
I have a following table:
id, name, surname, timestamp, type
type has two possible values: 1 and 2.
Now, I would like to find two rows - for each group (1 and 2) row with maximal value in particular type.
The problem is that I would like to find both name and surname.
I can do it with SELECT TOP 1 - WHERE ORDER BY - UNION approach, but I would like to find antother, better idea.
Can you help me ?

This sounds like you want the most recent for each row, for each type. If that's the case, here is a way with row_number()
with cte as(
select
id
,name
,surname
,timestamp
,type
RN = row_number() over (partition by id,type order by timestamp desc))
select *
from cte
where RN = 1

Related

SQL autoincrement value based on column

I have case in which I want same autoincrement value in new created column for same business code
I have tried below but I am not getting expected result
select *
, rank() over (partition by business_code order by ID)
from table
I am getting same same value in ID column for all business code which is not desired result.
My Output
Expected Output
Can you try the the following SQL statement:
SELECT id
,business_code
,DENSE_RANK() OVER (ORDER BY m) NewColumn
FROM (SELECT id
,business_code
,MIN(id) OVER (PARTITION BY business_code) m
FROM myTable) d
An explanation how it works: because of provided data i thought to get the minimum id of each business_code first. And as second step ranking that minimum id by value.
Use this
select row_number() over (order by (select null)), a.*
from Table a;

Automating Repeated Unions

I'm running a query like this:
SELECT id FROM table
WHERE table.type IN (1, 2, 3)
LIMIT 15
This returns a random sampling. I might have 7 items from class_1 and 3 items from class_2. I would like to return exactly 5 items from each class, and the following code works:
SELECT id FROM (
SELECT id, type FROM table WHERE type = 1 LIMIT 5
UNION
SELECT id, type FROM table WHERE type = 2 LIMIT 5
UNION ...
ORDER BY type ASC)
This gets unwieldy if I want a random sampling from ten classes, instead of only three. What is the best way to do this?
(I'm using Presto/Hive, so any tips for those engines would be appreciated).
Use a function like row_number to do this. This makes the selection independent of the number of types.
SELECT id,type
FROM (SELECT id, type, row_number() over(partition by type order by id) as rnum --adjust the partition by and order by columns as needed
FROM table
) T
WHERE rnum <= 5
I would strongly suggest adding ORDER BY. Anyway, you can do something like:
with
x as (
select
id,
type,
row_number() over(partition by type order by id) as rn
from table
)
select * from x where rn <= 5

SQL SERVER QUERY to select max value record per item

This is the sample table
What I need to achieve is to get or display only the record of tenant with the highest month value. If ever month is equal, I need to base on the latest date value. Here is the sample desired output
With this, I started by this code using max function and incorporated temp table, but unable to get the desired result.
select tenant, name, date, month
into #sample
from tenant
select *
from #sample
where months = (select max(months)from #sample)
and output to something like this. As I believe, the code is getting the max value in the whole list not considering per tenant filtering.
Any help will be greatly appreciated :)
This can be done with the row_number window function:
select tenant, name, date, months
from (select t.*,
row_number() over (partition by t.tenant, t.name order by t.months desc, t.date desc) as rn
from TableName t) x
where rn = 1
You can use a row_number function.
Query
;with cte as
(
select rn = row_number() over
(
partition by tenant
order by months desc,[date] desc
),*
from table_name
)
select tenant,name,[date],months from cte
where rn = 1;

how to get the distinct records based on maximum date?

I'm working with Sql server 2008.i have a table contains following columns,
Id,
Name,
Date
this table contains more than one record for same id.i want to get distinct id having maximum date.how can i write sql query for this?
Use the ROW_NUMBER() function and PARTITION BY clause. Something like this:
SELECT Id, Name, Date FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Id ORDER BY Date desc) AS ROWNUM
FROM [MyTable]
) x WHERE ROWNUM = 1
If you need only ID column and other columns are NOT required, then you don't need to go with ROW_NUMBER or MAX or anything else. You just do a Group By over ID column, because whatever the maximum date is you will get same ID.
SELECT ID FROM table GROUP BY ID
--OR
SELECT DISTINCT ID FROM table
If you need ID and Date columns with maximum date, then simply do a Group By on ID column and select the Max Date.
SELECT ID, Max(Date) AS Date
FROM table
GROUP BY ID
If you need all the columns but 1 line having Max. date then you can go with ROW_NUMBER or MAX as mentioned in other answers.
SELECT *
FROM table AS M
WHERE Exists(
SELECT 1
FROM table
WHERE ID = M.ID
HAVING M.Date = Max(Date)
)
One way, using ROW_NUMBER:
With CTE As
(
SELECT Id, Name, Date, Rn = Row_Number() Over (Partition By Id
Order By Date DESC)
FROM dbo.TableName
)
SELECT Id --, Name, Date
FROM CTE
WHERE Rn = 1
If multiple max-dates are possible and you want all you could use DENSE_RANK instead.
Here's an overview of sql-server's ranking function: http://technet.microsoft.com/en-us/library/ms189798.aspx
By the way, CTE is a common-table-expression which is similar to a named sub-query. I'm using it to be able to filter by the row_number. This approach allows to select all columns if you want.
select Max(Date) as "Max Date"
from table
group by Id
order by Id
Try with Max(Date) and GROUP BY the other two columns (the ones with repeating data)..
SELECT ID, Max(Date) as date, Name
FROM YourTable
GROUP BY ID, Name
You may try with this
DECLARE #T TABLE(ID INT, NAME VARCHAR(50),DATE DATETIME)
INSERT INTO #T VALUES(1,'A','2014-04-20'),(1,'A','2014-04-28')
,(2,'A2','2014-04-22'),(2,'A2','2014-04-24')
,(3,'A3','2014-04-20'),(3,'A3','2014-04-28')
,(4,'A4','2014-04-28'),(4,'A4','2014-04-28')
,(5,'A5','2014-04-28'),(5,'A5','2014-04-28')
SELECT T.ID FROM #T T
WHERE T.DATE=(SELECT MAX(A.DATE)
FROM #T A
WHERE A.ID=T.ID
GROUP BY A.ID )
GROUP BY T.ID
select id, max(date) from NameOfYourTable group by id;

How to select a row based on its row number?

I'm working on a small project in which I'll need to select a record from a temporary table based on the actual row number of the record.
How can I select a record based on its row number?
A couple of the other answers touched on the problem, but this might explain. There really isn't an order implied in SQL (set theory). So to refer to the "fifth row" requires you to introduce the concept
Select *
From
(
Select
Row_Number() Over (Order By SomeField) As RowNum
, *
From TheTable
) t2
Where RowNum = 5
In the subquery, a row number is "created" by defining the order you expect. Now the outer query is able to pull the fifth entry out of that ordered set.
Technically SQL Rows do not have "RowNumbers" in their tables. Some implementations (Oracle, I think) provide one of their own, but that's not standard and SQL Server/T-SQL does not. You can add one to the table (sort of) with an IDENTITY column.
Or you can add one (for real) in a query with the ROW_NUMBER() function, but unless you specify your own unique ORDER for the rows, the ROW_NUMBERS will be assigned non-deterministically.
What you're looking for is the row_number() function, as Kaf mentioned in the comments.
Here is an example:
WITH MyCte AS
(
SELECT employee_id,
RowNum = row_number() OVER ( order by employee_id )
FROM V_EMPLOYEE
ORDER BY Employee_ID
)
SELECT employee_id
FROM MyCte
WHERE RowNum > 0
There are 3 ways of doing this.
Suppose u have an employee table with the columns as emp_id, emp_name, salary. You need the top 10 employees who has highest salary.
Using row_number() analytic function
Select * from
( select emp_id,emp_name,row_number() over (order by salary desc) rank
from employee)
where rank<=10
Using rank() analytic function
Select * from
( select emp_id,emp_name,rank() over (order by salary desc) rank
from employee)
where rank<=10
Using rownum
select * from
(select * from employee order by salary desc)
where rownum<=10;
This will give you the rows of the table without being re-ordered by some set of values:
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT '1')) AS RowID, * FROM #table
If using SQL Server 2012 you can now use offset/fetch:
declare #rowIndexToFetch int
set #rowIndexToFetch = 0
select
*
from
dbo.EntityA ea
order by
ea.Id
offset #rowIndexToFetch rows
fetch next 1 rows only