How do you select all nth rows for each ID?
My table looks somewhat like this :
ID fName data
1 Hari 20
1 Hari 30
2 John 89
2 John 38
2 John 55
In this case, how do you select all 2nd rows for each ID?
The result would look like this :
ID fName data
1 Hari 30
2 John 38
This will help in SQL SERVER 2012:
SELECT ID, FNAME, DATA FROM
(
SELECT TEST_DATA.*,
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY ORDER_BY_CONDITION) AS RANK
FROM TEST_DATA
) T
WHERE T.RANK=2
Change your order by condition(ORDER_BY_CONDITION accordingly
Fiddle for SQL SERVER 2012 here: http://sqlfiddle.com/#!6/f59a1/3
EDIT: For multiple tables, you can try with CTE as in the fiddle : http://sqlfiddle.com/#!6/8a5b1d/10
Does the following query work for you? (Replace the <tablename> and the <datecolumn> names)
SELECT tbl.*
FROM <tablename> tbl
INNER JOIN
(
SELECT
ID,
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY <datecolumn>) rn
FROM <tablename>
) row_numbers
ON tbl.ID = row_numbers.ID AND tbl.<datecolumn> = row_numbers.<datecolumn> AND row_numbers.rn = 2;
Reference:
ROW_NUMBER function on MSDN
Using a CTE and ROW_NUMBER()...
;
WITH cteData ( ID, fName, data )
AS ( SELECT ID ,
fName ,
data ,
ROW_NUMBER()
OVER ( PARTITION BY ID ORDER BY DateField ) AS 'rowNum'
FROM tblName
)
SELECT ID ,
fName ,
data
FROM cteData
WHERE rowNum = 2--Im assuming 2 from the data presented in question
Related
How to remove duplicate records from a view? I need to keep them on the physical table, but in the view, I don't want the duplicates
Here is the query I used:
CREATE VIEW myview
AS
SELECT DISTINCT *
FROM [roug].[dbo].[Table_1]
ORDER BY id
for the table :
id| name age
----------
c1 ann 12
u2 joe 15
c1 ann 12
c1 ann 12
u5 dev 13
u3 Jim 16
u3 Jim 16
You can either use DISTINCT or ROW_NUMBER() Like this
create view myview as
WITH CTE
AS
(
SELECT
RN = ROW_NUMBER() OVER(PARTITION BY [Id],[Name],[Age] ORDER BY ID),
*
FROM [roug].[dbo].[Table_1]
)
SELECT
[Id],[Name],[Age]
FROM CTE
WHERE RN = 1
If you want to delete data then you should be doing it in the source table not the view. A standard approach for de-duping is via a cte. Try
;
WITH cte
AS (SELECT id
, name
, age
, ROW_NUMBER() OVER (PARTITION BY id, name, age ORDER BY id) RN
FROM Table_1
)
DELETE FROM cte
WHERE RN > 1
Depends on if you want to delete the actual data, or just not display it in the view.
I have a select statement in which I am using in clause.
Here is my table : MyTable
Id SKU
1 112
2 223
3 445
4 456
5 678
If I write:
SELECT Id
FROM MyTable
WHERE SKU IN (112,223,445, 456, 678)
I an not getting result as
1
2
3
4
5
Is there any way to get select result based on items order in the in clause.?
For your case ORDER BY id will be sufficient.
SELECT Id
FROM MyTable
WHERE SKU IN (112,223,445, 456, 678)
ORDER BY id
For general approach you could use JOIN with derived table like:
Demo
SELECT m.Id
FROM MyTable m
JOIN (VALUES (1, 112) ,(2,223) ,(3,445), (4,456), (5,678)) AS t(num, SKU)
ON m.SKU = t.SKU
ORDER BY t.num
If you use SQL Server 2008 you can use UNION ALL:
Demo2
;WITH cte AS
(
SELECT 112 AS SKU, 1 AS orderNum
UNION ALL
SELECT 223 AS SKU, 2 AS orderNum
UNION ALL
SELECT 445 AS SKU, 3 AS orderNum
UNION ALL
SELECT 456 AS SKU, 4 AS orderNum
UNION ALL
SELECT 678 AS SKU, 5 AS orderNum
)
SELECT m.Id
FROM #MyTable m
JOIN cte c
ON m.SKU = c.SKU
ORDER BY c.orderNum;
General approach that does not force you to create custom query you could use temp table with IDENTITY column like:
Demo3
CREATE TABLE #mySKU( orderNum INT IDENTITY(1,1), SKU INT);
INSERT INTO #mySKU
VALUES (112),(223),(445), (456), (678);
SELECT m.Id
FROM #MyTable m
JOIN #mySKU c
ON m.SKU = c.SKU
ORDER BY c.orderNum;
"Is there any way to get select result based on items order in the in clause?"
For this particular question the answer is no.
[![enter image description here][1]][1]I need help with the following query.
select *
from xr.ObjectPropertyvalue
where objectid in (
select objectid
from xr.objectpropertyvalue
where endversion in
(select max(endversion)
from xr.ObjectPropertyValue
group by objectid having count(endversion) > 1
)
)
What I was trying to do is to look for an entry on the table that has the highest end version and the objectid being unique.
Ex.
Object id 1's highest version = 3
Object id 2 highest version =4
Any help would be appreciated.
If I understood correctly, you may try this query (un-tested, I don't have sql-server environment now)
WITH cte AS (
SELECT *, rn = ROW_NUMBER() OVER(PARTITION BY objectid ORDER BY endversion DESC)
FROM xr.ObjectPropertyvalue
)
SELECT *
FROM cte c
WHERE c.rn = 1
AND EXISTS (SELECT 1 FROM cte c2 WHERE c2.objectid = c.objectid AND c2.rn = 2)
ORDER BY c.objectid
I have a SQL Server table. This table has two tables: Order and OrderInProgress. These two tables have similar structures:
Order[InProgress]
-----------------
ID (uniqueidentifier)
CreateDate
...
I need to get the latest Order or OrderInProgress
DECLARE #latestOrderID uniqueidentifier
#latestOrderID = ?
How do I set #latestOrderID to the most recent Order or OrderInProgress ID? I can't figure out how to do this in SQL.
Thank you!
Try this, which should be more efficient whenever it matters.
select top 1 ID from (
select top 1 ID from Order order by ID desc
union all
select top 1 ID from OrderInProgress order by ID desc
) T
order by ID desc
Have you tried:
SELECT TOP 1 #latestOrderID = ID FROM [Order] ORDER BY CreateDate DESC
SELECT * FROM
(SELECT 'Order' tablename, max(ID) max_id FROM Order
UNION
SELECT 'OrderInProgress' tablename, max(ID) max_id FROM OrderInProgress
) maxes ORDER BY max_id DESC
I have a table with the following columns in SQL Server:
MEMBERID, MEMBEREMAIL, FATHEREMAIL, MOTHEREMAIL, MEMBERNAME
MEMBERID is PK. The three email columns are not unique, so the same email may appear several times in the same row AND in several rows.
I am trying to extract a unique list of emails, and for each email also get a memberid and membername (it does not matter from which record).
For example if I have three rows:
1 x#x.com y#y.com y#y.com Mark
2 z#z.com y#y.com x#x.com John
3 x#x.com y#y.com z#z.com Susan
I want to get the three emails (x#x.com, y#y.com, z#z.com) and for each of those a MEMBERID in which they appear. It does NOT which MEMBERID (for example for x#X.com I don't care if I get the values 1 and Mark or 2 and John or 3 and Susan, as long as x#x.com appears only once in the results.
If I use DISTINCT when trying to return the email and memberid and membername, of course I get all of the rows.
You could use a subquery to normalize all emails. Then you can use row_number to filter out one memberid, membername per email:
select *
from (
select row_number() over (partition by email order by memberid) as rn
, *
from (
select MEMBERID
, MEMBERNAME
, MEMBEREMAIL as email
from YourTable
union all
select MEMBERID
, MEMBERNAME
, FATHEREMAIL
from YourTable
union all
select MEMBERID
, MEMBERNAME
, MOTHEREMAIL
from YourTable
) as emails
) num_emails
where rn = 1
You could also normalize the emails using the UNPIVOT clause, like this:
select *
from (
select row_number() over (partition by email order by memberid) as rn
, *
from (
select MEMBERID
, MEMBERNAME
, email
from YourTable
unpivot (
email
for emailOwner
in (
MEMBEREMAIL,
FATHEREMAIL,
MOTHEREMAIL
)
) as u
) as emails
) num_emails
where rn = 1
Try both versions at SQL Fiddle:
UNION ALL version
UNPIVOT version
This code will give you the right group of distinct emails:
then you can create a cursor out of the query members and then get the comma seperated list of mails per memberid with this concept I would create an output table for this will be easyer if you need it for future use and would make a store procedure for this to create the custom table
select mem.*, mails.MEMBEREMAIL
from (
select MEMBERID,max(MEMBERNAME) as MEMBERNAME
from table
group by MEMBERID
) as mem
inner join
(
select distinct MEMBERID, MEMBEREMAIL
from (
select MEMBERID, MEMBEREMAIL
from table
union
select MEMBERID, FATHEREMAIL
from table
union
select MEMBERID, MOTHEREMAIL
from table
) as mail
) as mails on mem.MEMBERID = mails.MEMBERID