Display max value rows only - sql-server

I have the following table (must shorter version than the real one),
and I want to all the rows with max _ values for each _ displayed.
How should I do this?
Table Now
Table I want to have
thanks a lot in advance!!

Using the dense_rank function and a derived table would be appropriate for this (please note I used underscores instead of spaces in the column names):
select group_type
,desk_number
,comments
from
(select *
,dense_rank() over(partition by group_type order by desk_number desc) dr
from mytable) t1
where t1.dr = 1
I made a rextester sample that you can try here
Let me know if you have any questions.

How can I SELECT rows with MAX(Column value), DISTINCT by another column in SQL?
This answers your question quite well but I will convert it for your convenience <3
SELECT *
FROM table
INNER JOIN
(SELECT comments, MAX([desk number]) AS MaxDesk
FROM table
GROUP BY comments) groupedtable
ON table.[desk number]= groupedtable.[desk number]
AND table.comments= groupedtable.MaxDesk

try this :
WITH CTE
AS
(
SELECT
SeqNo = ROW_NUMBER() OVER(ORDER BY CAST(DeskNumber AS INT) DESC PARTITION BY GroupType),
GroupType,
DeskNumber,
[Comment]
FROM YourTable
)
SELECT
*
FROM CTE WHERE CTE.SeqNo = 1

Related

How to select highest common value across groups

`Suppose I have a set of data with 2 fields - Type and Date. I am interested in finding (if exists) the the max common date across the various types. Is this easier to do in SQL or LINQ?
Given the data below the result should be 2018-02-01 as this is the max common date for all types. It there is no such date then no data is returned.
Type, Date
---------
1,2018-03-01
1,2018-02-01
1,2018-01-01
2,2018-02-01
2,2018-05-01
2,2018-01-01
3,2018-01-01
3,2018-03-01
3,2018-02-01
You could use:
SELECT TOP 1 [Date], COUNT(*) OVER(PARTITION BY Date) AS cnt
FROM tab
ORDER BY cnt DESC, [Date] DESC
DBFiddle Demo
This'll work if you have an unlimited or indeterminable number of Types:
CREATE TABLE #Sample ([Type] int, [DAte] date);
INSERT INTO #Sample
VALUES
(1,'20180301'),
(1,'20180201'),
(1,'20180101'),
(2,'20180201'),
(2,'20180501'),
(2,'20180101'),
(3,'20180101'),
(3,'20180301'),
(3,'20180201');
GO
WITH EntryCount AS(
SELECT [Type], [Date],
COUNT(*) OVER (PARTITION By [Date]) AS Entries
FROM #Sample)
SELECT MAX(Date)
FROM EntryCount EC
WHERE Ec.Entries = (SELECT COUNT(DISTINCT sq.[Type]) FROM #Sample sq);
GO
DROP TABLE #Sample;
Not sure how quick it'll be either though.
Example
Select Top 1 [Date]
from YourTable
Group By [Date]
Order By count([Type]) desc,[Date] desc
Returns
2018-02-01
This is not going to be very efficient not matter how you slice it because you have to compare across three groups. Assuming you have 3 types you could use a self join. Something like this.
select MAX(YourDate)
from YourTable yt
join YourTable yt2 on yt2.YourType = 2 and yt.YourDate = yt2.YourDate
join YourTable yt3 on yt3.YourType = 3 and yt.YourDate = yt3.YourDate
where yt.YourType = 1

SQL Server show only rows (all columns) with a distinct column name

I have a query which produces several results. I have concatenated several columns into 1 as an ID. I only want to show the rows where the ID is unique.
The below image is an example of my table:
As you can see the ID is repeated a few times. How can I construct a query to show only the 3 unique rows?
Nesting this query and using distinct(RowID) shows the three rows but I cannot show the rest of the columns?
Any ideas welcome. Thank you!
Use distinct in the select for all columns
Query:
select distinct RowID, OrderNum, cDescription, Thickness, UllTimberThickness, Width, UllTimberWidth, Length
from YourTable
Use GROUP BY:
SELECT RowID, OrderNum, cDescription, Thickness, etcetera ...
FROM dbo.TableName
GROUP BY RowID, OrderNum, cDescription, Thickness, etcetera ...
( etcetera is a placeholder for the rest of your columns )
Try this:
SELECT *
FROM mytable t1
WHERE
(SELECT COUNT(*) FROM mytable t2
where t2.id = t1.id) = 1
In this way, you get all rows where id is unique. I write this query because I don't know if at your ID other fields are the same, because you have built your field with a set of information. If all the columns are the same for equal id so you can use the statement DISTINCT as adviced you by Vasanth Sundaralingam in his post.
I'm a little confused by what "get the three unique rows means".
If you mean rows that are unique, use count(*) as a window function:
select *
from (select t.*,
count(*) over (partition by id) as cnt
from t
) t
where cnt = 1;
If you mean one example of each row, use row_number():
select *
from (select t.*,
row_number(*) over (partition by id order by (select NULL)) as seqnum
from t
) t
where seqnum = 1;

SQL Update with row_number()

I want to update my column CODE_DEST with an incremental number. I have:
CODE_DEST RS_NOM
null qsdf
null sdfqsdfqsdf
null qsdfqsdf
I would like to update it to be:
CODE_DEST RS_NOM
1 qsdf
2 sdfqsdfqsdf
3 qsdfqsdf
I have tried this code:
UPDATE DESTINATAIRE_TEMP
SET CODE_DEST = TheId
FROM (SELECT Row_Number() OVER (ORDER BY [RS_NOM]) AS TheId FROM DESTINATAIRE_TEMP)
This does not work because of the )
I have also tried:
WITH DESTINATAIRE_TEMP AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY [RS_NOM] DESC) AS RN
FROM DESTINATAIRE_TEMP
)
UPDATE DESTINATAIRE_TEMP SET CODE_DEST=RN
But this also does not work because of union.
How can I update a column using the ROW_NUMBER() function in SQL Server 2008 R2?
One more option
UPDATE x
SET x.CODE_DEST = x.New_CODE_DEST
FROM (
SELECT CODE_DEST, ROW_NUMBER() OVER (ORDER BY [RS_NOM]) AS New_CODE_DEST
FROM DESTINATAIRE_TEMP
) x
DECLARE #id INT
SET #id = 0
UPDATE DESTINATAIRE_TEMP
SET #id = CODE_DEST = #id + 1
GO
try this
http://www.mssqltips.com/sqlservertip/1467/populate-a-sql-server-column-with-a-sequential-number-not-using-an-identity/
With UpdateData As
(
SELECT RS_NOM,
ROW_NUMBER() OVER (ORDER BY [RS_NOM] DESC) AS RN
FROM DESTINATAIRE_TEMP
)
UPDATE DESTINATAIRE_TEMP SET CODE_DEST = RN
FROM DESTINATAIRE_TEMP
INNER JOIN UpdateData ON DESTINATAIRE_TEMP.RS_NOM = UpdateData.RS_NOM
Your second attempt failed primarily because you named the CTE same as the underlying table and made the CTE look as if it was a recursive CTE, because it essentially referenced itself. A recursive CTE must have a specific structure which requires the use of the UNION ALL set operator.
Instead, you could just have given the CTE a different name as well as added the target column to it:
With SomeName As
(
SELECT
CODE_DEST,
ROW_NUMBER() OVER (ORDER BY [RS_NOM] DESC) AS RN
FROM DESTINATAIRE_TEMP
)
UPDATE SomeName SET CODE_DEST=RN
This is a modified version of #Aleksandr Fedorenko's answer adding a WHERE clause:
UPDATE x
SET x.CODE_DEST = x.New_CODE_DEST
FROM (
SELECT CODE_DEST, ROW_NUMBER() OVER (ORDER BY [RS_NOM]) AS New_CODE_DEST
FROM DESTINATAIRE_TEMP
) x
WHERE x.CODE_DEST <> x.New_CODE_DEST AND x.CODE_DEST IS NOT NULL
By adding a WHERE clause I found the performance improved massively for subsequent updates. Sql Server seems to update the row even if the value already exists and it takes time to do so, so adding the where clause makes it just skip over rows where the value hasn't changed. I have to say I was astonished as to how fast it could run my query.
Disclaimer: I'm no DB expert, and I'm using PARTITION BY for my clause so it may not be exactly the same results for this query. For me the column in question is a customer's paid order, so the value generally doesn't change once it is set.
Also make sure you have indexes, especially if you have a WHERE clause on the SELECT statement. A filtered index worked great for me as I was filtering based on payment statuses.
My query using PARTITION by
UPDATE UpdateTarget
SET PaidOrderIndex = New_PaidOrderIndex
FROM
(
SELECT PaidOrderIndex, SimpleMembershipUserName, ROW_NUMBER() OVER(PARTITION BY SimpleMembershipUserName ORDER BY OrderId) AS New_PaidOrderIndex
FROM [Order]
WHERE PaymentStatusTypeId in (2,3,6) and SimpleMembershipUserName is not null
) AS UpdateTarget
WHERE UpdateTarget.PaidOrderIndex <> UpdateTarget.New_PaidOrderIndex AND UpdateTarget.PaidOrderIndex IS NOT NULL
-- test to 'break' some of the rows, and then run the UPDATE again
update [order] set PaidOrderIndex = 2 where PaidOrderIndex=3
The 'IS NOT NULL' part isn't required if the column isn't nullable.
When I say the performance increase was massive I mean it was essentially instantaneous when updating a small number of rows. With the right indexes I was able to achieve an update that took the same amount of time as the 'inner' query does by itself:
SELECT PaidOrderIndex, SimpleMembershipUserName, ROW_NUMBER() OVER(PARTITION BY SimpleMembershipUserName ORDER BY OrderId) AS New_PaidOrderIndex
FROM [Order]
WHERE PaymentStatusTypeId in (2,3,6) and SimpleMembershipUserName is not null
I did this for my situation and worked
WITH myUpdate (id, myRowNumber )
AS
(
SELECT id, ROW_NUMBER() over (order by ID) As myRowNumber
FROM AspNetUsers
WHERE UserType='Customer'
)
update AspNetUsers set EmployeeCode = FORMAT(myRowNumber,'00000#')
FROM myUpdate
left join AspNetUsers u on u.Id=myUpdate.id
Simple and easy way to update the cursor
UPDATE Cursor
SET Cursor.CODE = Cursor.New_CODE
FROM (
SELECT CODE, ROW_NUMBER() OVER (ORDER BY [CODE]) AS New_CODE
FROM Table Where CODE BETWEEN 1000 AND 1999
) Cursor
If table does not have relation, just copy all in new table with row number and remove old and rename new one with old one.
Select RowNum = ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) , * INTO cdm.dbo.SALES2018 from
(
select * from SALE2018) as SalesSource
In my case I added a new column and wanted to update it with the equevilat record number for the whole table
id name new_column (ORDER_NUM)
1 Ali null
2 Ahmad null
3 Mohammad null
4 Nour null
5 Hasan null
6 Omar null
I wrote this query to have the new column populated with the row number
UPDATE My_Table
SET My_Table.ORDER_NUM = SubQuery.rowNumber
FROM (
SELECT id ,ROW_NUMBER() OVER (ORDER BY [id]) AS rowNumber
FROM My_Table
) SubQuery
INNER JOIN My_Table ON
SubQuery.id = My_Table.id
after executing this query I had 1,2,3,... numbers in my new column
I update a temp table with the first occurrence of part where multiple parts can be associated with a sequence number. RowId=1 returns the first occurence which I join the tmp table and data using part and sequence number.
update #Tmp
set
#Tmp.Amount=#Amount
from
(SELECT Part, Row_Number() OVER (ORDER BY [Part]) AS RowId FROM #Tmp
where Sequence_Num=#Sequence_Num
)data
where data.Part=#Tmp.Part
and data.RowId=1
and #Tmp.Sequence_Num=#Sequence_Num
I don't have a running ID in order to do what "Basheer AL-MOMANI" suggested.
I did something like this: (joined my table on myself, just to get the Row Number)
update T1 set inID = T2.RN
from (select *, ROW_NUMBER() over (order by ID) RN from MyTable) T1
inner join (select *, ROW_NUMBER() over (order by ID) RN from MyTable) T2 on T2.RN = T1.RN

Taking the second last row with only one select in SQL Server?

I was trying to select the second last row with SQL Server. So I wrote a query like this:
SELECT TOP 1 * From Cinema
WHERE CinemaID!=(SELECT TOP 1 CinemaID
FROM Cinema
ORDER BY CinemaID DESC)
ORDER BY CinemaID DESC
and it did what I need. But I want to do the same thing with only one select.
I read that the LIMIT clause in MySql does that. But I couldn't find any equivalent
of that. So I appreciate any help about finding something useful.
To get the 2nd last row in one select:
SELECT TOP 1 * From
(select Top 2 * from Cinema ORDER BY CinemaID DESC) x
ORDER BY CinemaID
It's really only "one" select because the outer select is over only 2 rows.
The best way to do this (and compatible with the ANSI SQL standard), is to use a CTE (Common Table Expression) with the ROW_NUMBER function:
;WITH OrderedCinemas AS
(
SELECT
CinemaID, CinemaName,
ROW_NUMBER() OVER(ORDER BY CinemaID DESC) AS 'RowNum'
FROM dbo.Cinema
)
SELECT
CinemaID, CinemaName
FROM OrderedCinemas
WHERE RowNum = 2
By using this construction, you can get the second highest value very easily - or the fifth hightest (WHERE RowNum = 5) or the top 3 rows (WHERE RowNum <= 3) or whatever you need - the CinemaID values are just ordered and sequentially numbered for your use.
The following doesn't work, explaination of why:
Using ranking-function derived column in where clause (SQL Server 2008)
I'll keep it here for completeness:
SELECT row_number() OVER (ORDER BY col) r, *
FROM tbl
WHERE r = 2
More info:
http://www.bidn.com/blogs/marcoadf/bidn-blog/379/ranking-functions-row_number-vs-rank-vs-dense_rank-vs-ntile
So I think the most readable way of doing it is:
SELECT * FROM (SELECT row_number() OVER (ORDER BY col) r, * FROM tbl) q
WHERE r = 2
Since this (old) question has not been tagged with a specific SQL-Server version and none of (the very good) answers uses only one SELECT clause - for the good reason that it was not possible in old verions - here is one that works only in recent, 2012+ versions:
SELECT c.*
FROM dbo.Cinema AS c
ORDER BY CinemaID DESC
OFFSET 1 ROW
FETCH FIRST 1 ROW ONLY ;
Tested at SQLFiddle
SELECT TOP 1 * FROM tbl_CompanyMaster
where Companyid >= (SELECT MAX(Companyid) - 1 FROM tbl_CompanyMaster)
select * from TABLE_NAME order by COLUMN_NAME desc limit 1,1 ;
Where COLUMN_NAME should be "primary key" or "Unique"
Two selects but a bit quicker
select top 1 * from(
SELECT TOP 2 * From Cinema
WHERE CinemaID
ORDER BY CinemaID DESC) top2
Order by CinemaID
So, in the spirit of only using one SELECT clause as stated in the OP and thoroughly abusing T-SQL in general, I proffer something I would never, ever recommend using in production that nevertheless satisfies the stated criteria:
update Cinema
set Cinema.SomeField = Cinema.SomeField
output inserted.*
from Cinema
inner join
(
select top 2 CinemaID, ROW_NUMBER() over (order by CinemaID desc) as RowNum
from Cinema
) rsRowNum on rsRowNum.CinemaID = Cinema.CinemaID
where RowNum = 2
This query will also work for SQLITE
SELECT * From
(select * from Cinema ORDER BY CinemaID DESC LIMIT 2) AS name
ORDER BY CinemaID LIMIT 1
You're only using one SELECT statement. A SELECT statement can include an arbitrary (more or less) number of subqueries--correlated subqueries, scalar subqueries, and so on, each with their own SELECT clause. But it's still just one SELECT statement.
If you want to avoid a subquery, you could select the top 2, and skip the one you don't want. That kind of programming is pretty brittle, though. You have to remember what to skip every time; sooner or later, you'll forget.
SELECT field_name FROM (SELECT TOP 2 field_name FROM table_name
ORDER BY field_name DESC)
WHERE rownum = 2;
select top 1* from(SELECT TOP 2 * From Cinema
WHERE CinemaID
ORDER BY CinemaID DESC) XYZ
ORDER BY CinemaID
where XYZ is not a keyword. It is just a word. And word can be anything.
If you need to do that, but:
the column is different than id
you need to order by some specific column
can't use SELECT on FROM clause (if you are using old versions of Hibernate, per example).
You can do:
select top 1 * from Cinema
where date < (select MAX(date) from Cinema)
order by date desc
The easiest way to get second last row from sql table is user ORDER BY CinemaID DESC and set LIMIT 1,1
TRY THIS
SELECT * from `Cinema` ORDER BY `CinemaID` DESC LIMIT 1,1
select * from
(select ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) as R, * from Cinema ) T1
where (select count(*) from Cinema ) - T1.R = 1
SELECT * FROM record
WHERE record_id=(SELECT max(record_id)-1 FROM record)
Here is my code:
SELECT * From
(select * from table name ORDER BY column name DESC LIMIT 2) AS xyz
ORDER BY column name LIMIT 1;

SQL SERVER : select the latest comment using the max date

I have a table like so:
Id, Comment, LastUpdatedDate
I'm tyring to select the latest comment for that id. The table can have many comments on that id with different dates but I'm trying to get the latest date out of there. I've tried the following with no success:
SELECT tt.*
FROM tagtestresultcomment tt
INNER JOIN
(
SELECT tag_id, MAX(last_update) AS MaxDateTime
FROM tagtestresultcomment
GROUP BY tag_id
) groupedtt ON tt.tag_id = groupedtt.tag_id AND tt.last_update = groupedtt.MaxDateTime
order by tag_id
Does anyone have any ideas of how to achieve this?
Thanks!
It sounds like you want only the latest comment for each tag_id? In which case, here is one approach you can use from SQL 2005 and on:
;WITH CTE AS
(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY tag_id ORDER BY last_update DESC) AS RowNo
FROM TagTestResultComment
)
SELECT * FROM CTE WHERE RowNo = 1
try this
Select * from tagtestresultcomment where last_update in
(select max(last_update) from tagtestresultcomment group by tag_id)
your query code is too redundant. first
tt.tag_id = groupedtt.tag_id AND tt.last_update = groupedtt.MaxDateTime
it's enough just
tt.tag_id = groupedtt.tag_id
and second, it's enough just
SELECT [desired field list extcept last_update and ],
tag_id,
MAX(last_update) AS MaxDateTime
FROM
tagtestresultcomment
group by
tag_id, [desired field list extcept last_update and tag_id]
at all to achieve your objective
I have tried something like this:
declare #tagtestresultcomment table
(
id int
, comment varchar(50)
,LastUpdatedDate datetime
)
--==== Populate table
insert into #tagtestresultcomment(id,comment,LastUpdatedDate)
select 1,'My name is Arthur','2011-06-09 00:00:00' union all
select 2,'My name is DW','2011-06-19 00:00:00' union all
select 2,'Arthur is my brother','2011-06-21 00:00:00' union all
select 1,'I have a sister named DW','2011-06-21 00:00:00' union all
select 3,'I am Muffy','2011-06-14 00:00:00' union all
select 3,'I like sports','2011-06-14 00:00:00'
-- SELECT stmt
select * from #tagtestresultcomment t
join
(
select id, MAX(lastupdateddate) as LastUpdatedDate from #tagtestresultcomment group by id
) m
on t.id = m.id
and t.LastUpdatedDate = m.LastUpdatedDate
The "MAX" group function wasn't working for me, so I used a sub-query. I had trouble wrapping my head around your single table example, so I'm using a common parent-child 1-to-many relationship with a blog and comment tables as an example.
SELECT
b.id,
b.content,
c.id,
c.blog_id,
c.content,
c.last_update
FROM blog b
INNER JOIN blog_comment c
ON b.id = c.blog_id AND c.id = (
SELECT TOP 1 id FROM blog_comment WHERE blog_id = b.id ORDER BY last_update DESC
)
The query takes a hit on my sub-query, as it will call that "SELECT TOP 1" query for each record in the blog table. I'd like to hear of a faster, more efficient example if possible.

Resources