Row_Number() over partition query - sql

I have the following query:
declare #temp1 table
(ID1 int not null,
ID2 int not null)
set nocount off
insert into #temp1 values(1453,931)
insert into #temp1 values(1454,931)
insert into #temp1 values(1455,931)
insert into #temp1 values(2652,1101)
insert into #temp1 values(2653,1101)
insert into #temp1 values(2654,1101)
insert into #temp1 values(2655,1101)
insert into #temp1 values(2656,1101)
insert into #temp1 values(3196,1165)
insert into #temp1 values(3899,1288)
insert into #temp1 values(3900,1288)
insert into #temp1 values(3901,1288)
insert into #temp1 values(3902,1288)
--select * from #temp1
select ID1,ID2, ROW_NUMBER() over(partition by ID2 order by ID1) as RowNum1
from #temp1
What I now want to do is create a new column that will group all the ID2's together..i.e ID2's having 931 should have value 1 in the new column, 1101 should have 2, 1165 should be 3 and finally all 1288 should have 4... Can I get help for that please?

You can use DENSE_RANK() to attain the result. It returns the rank of rows within the partition of a result set, without any gaps in the ranking. The rank of a row is one plus the number of distinct ranks that come before the row in question. Refer link DENSE_RANK (Transact-SQL) for more details. Please try:
select ID1, ID2, DENSE_RANK() over(order by ID2) as RowNum1
from #temp1

Related

How to get the each record with some condition

I have following data:
DECLARE #temp TABLE (
ID int
,sn varchar(200)
,comment varchar(2000)
,rownumber int
)
insert into #temp values(1,'sn1',NULL,1)
insert into #temp values(2,'sn1','aaa',2)
insert into #temp values(3,'sn1','bbb',3)
insert into #temp values(4,'sn1',NULL,4)
insert into #temp values(5,'sn2',NULL,1)
insert into #temp values(6,'sn2',NULL,2)
insert into #temp values(7,'sn2',NULL,3)
select * from #temp
And I want to output like this:
2 sn1 aaa 2
5 sn2 NULL 1
same sn, if comment have value, get this lower rownumber's record. For sn1, have two records with comment value, so here, get the the record with rownumber=2
If comment doesn't have value, get the lower rownumber's record. For sn2, get the record with rownumber=1
May I know how to write this SQL?
This is a prioritization query. I think row_number() is the simplest method:
select t.*
from (select t.*,
row_number() over (partition by sn
order by (case when comment is not null then 1 else 2 end),
rownumber
) as seqnum
from #temp t
) t
where seqnum = 1;
Here is a db<>fiddle.

Deleting records that are similar with previous one SQL Server

I am looking for a query which fetches me the data that is different compared to the previous row,
A sample code (with table creation and data)
create table #temp
(id int, eid int, name char(10),estid int, ecid int, epid int, etc char(5) )
insert into #temp values (1,1,'a',1,1,1,'a')
insert into #temp values (2,1,'a',1,1,1,'a')
insert into #temp values (3,1,'a',2,1,1,'a')
insert into #temp values (4,1,'a',1,1,1,'a')
insert into #temp values (5,1,'a',1,1,1,'a')
insert into #temp values (6,1,'a',1,2,1,'a')
insert into #temp values (7,1,'a',1,1,1,'a')
insert into #temp values (8,1,'a',2,1,1,'a')
insert into #temp values (9,1,'a',1,1,1,'a')
insert into #temp values (10,1,'a',1,1,1,'a')
insert into #temp values (11,2,'a',1,1,1,'a')
insert into #temp values (12,2,'a',1,1,1,'a')
insert into #temp values (13,2,'a',2,1,1,'a')
insert into #temp values (14,2,'a',1,1,1,'a')
insert into #temp values (15,2,'a',1,1,1,'a')
insert into #temp values (16,2,'a',1,2,1,'a')
insert into #temp values (17,2,'a',1,1,1,'a')
insert into #temp values (18,2,'a',2,1,1,'a')
insert into #temp values (19,2,'a',1,1,1,'a')
insert into #temp values (20,2,'a',1,1,1,'a')
I tried with some ways of getting the data as the way that i expected
SELECT * INTo #Temp_Final
FROM #temp
WHERE #temp.%%physloc%%
NOT IN (SELECT Min(b.%%physloc%%)
FROM #temp b
GROUP BY eid,name,estid,ecid,epid,etc)
ORDER BY id
SELECT * FROM #temp WHERE id not in (SELECT id FROM #Temp_Final) ORDER BY id
But i wasn't getting the result as i expected...
This is how the result needs to be
select * from #temp where id in (1,3,4,6,7,8,9,11,13,14,16,17,18,19)
You can do this with a simple self-join and appropriate comparison:
select t.*
from #temp t left outer join
#temp tprev
on t.id = tprev.id + 1
where tprev.id is null or
t.name <> tprev.name or
t.estid <> tprev.estid or
t.ecid <> tprev.ecid or
t.epid <> tprev.epid or
t.etc <> tprev.etc;
This assumes that the ids are sequential with no gaps. If the ids are not, you can get the previous id using a correlated subquery or the lag() function.
Your title says "delete" but the question seems to just want the list of such rows. You can phrase this as a delete query if you need to.
For SQL Server 2012 (SQL Fiddle)
WITH CTE
AS (SELECT *,
LAG(eid) OVER (ORDER BY id) AS prev_eid,
LAG(name) OVER (ORDER BY id) AS prev_name,
LAG(estid) OVER (ORDER BY id) AS prev_estid,
LAG(ecid) OVER (ORDER BY id) AS prev_ecid,
LAG(epid) OVER (ORDER BY id) AS prev_epid,
LAG(etc) OVER (ORDER BY id) AS prev_etc
FROM #temp)
DELETE FROM CTE
WHERE EXISTS (SELECT eid,
name,
estid,
ecid,
epid,
etc
INTERSECT
SELECT prev_eid,
prev_name,
prev_estid,
prev_ecid,
prev_epid,
prev_etc)
select
t.id,
t.eid,
t.name,
t.estid,
t.ecid,
t.epid,
t.etc
from #temp t
left join #temp d
on d.id = t.id-1
and d.eid = t.eid
and d.name = t.name
and d.estid = t.estid
and d.ecid = t.ecid
and d.epid = t.epid
and d.etc = t.etc
where d.id is null

Insert into table from table variable?

DECLARE #t TABLE
(
ID uniqueidentifier,
ID2 uniqueidentifier
)
...insert into #t
...do stuff to #t
INSERT INTO testTable (Id, Id2) VALUES (SELECT ID, ID2 from #t) -does not work?
This is how you should do that:
INSERT INTO testTable (Id, Id2)
SELECT ID, ID2
from #t
How about this?
INSERT INTO testTable SELECT ID, ID2 from #t

SQL intersect with other tables, how do I ignore it?

I am trying to run a query given three tables.
DECLARE #TABLE1 TABLE (ID CHAR(2))
DECLARE #TABLE2 TABLE (ID CHAR(2))
DECLARE #TABLE3 TABLE (ID CHAR(2))
INSERT INTO #TABLE1 VALUES('1')
INSERT INTO #TABLE1 VALUES('2')
INSERT INTO #TABLE2 VALUES('1')
--NOTHING in TABLE3
I Need to get only the values that are present and ignore the null table. This doesn't work since TABLE3 has no values.
SELECT ID
FROM #TABLE1
INTERSECT
SELECT ID
FROM #TABLE2
INTERSECT
SELECT ID
FROM #TABLE3
**Result should be 1**
How do I ignore the any table if it's null but keep the other values?
Why not do a union of select distincts from each table, and then group that by ID and select count(*), and select only rows with count(*) equal to the maximum value of count(*) in the result?
It's a bit of a mess of subqueries at this point unfortunately but you should get the logic :)
Intersect is not going to work for you as you can't add conditions to it.
From what I understand you want to select all records where the ID appears in at least 2 of the tables. I am assuming that the ID is unique to each table.
The following works in MS SQL Server:
DECLARE #TABLE1 TABLE (ID CHAR(2))
DECLARE #TABLE2 TABLE (ID CHAR(2))
DECLARE #TABLE3 TABLE (ID CHAR(2))
INSERT INTO #TABLE1 VALUES('1')
INSERT INTO #TABLE1 VALUES('2')
INSERT INTO #TABLE2 VALUES('1')
--NOTHING in TABLE3
;WITH AllValues AS
(
SELECT ID
FROM #TABLE1
UNION ALL
SELECT ID
FROM #TABLE2
UNION ALL
SELECT ID
FROM #TABLE3
)
SELECT ID
FROM AllValues
GROUP BY ID
HAVING COUNT(*) > 1
Maybe... But the design of the system is extremely foreign; a real world example would help understand what you're trying to do.
Select count(*), ID FROM (
Select ID from #table1
UNION
Select ID from #table2
UNION
Select ID from #table3) Derived
Where RowNum =1
GROUP BY ID
ORder by count(*) DESC
Updated where clause was in wrong place

SQL Server sort column based on the same column itself

I have a db table containing a column display_order. The data looks like this:
2
4
7
10
12
I want to update the same db column and it should look like this:
1
2
3
4
5
Please suggest some easy SQL code.
Have a look into ROW_NUMBER(), this will help you here.
e.g. demo that won't update your data, but will show you the current order and the new order based on ROW_NUMBER
SELECT display_order AS CurrentDisplayOrder,
ROW_NUMBER() OVER (ORDER BY display_order) AS NewDisplayOrder
FROM YourTable
ORDER BY display_order
If that produces what you'd expect, then you can just switch it into an UPDATE statement.
Expanding on AdaTheDev's idea - using a CTE (Common Table Expression) makes it really easy to see how to use the actual UPDATE to update your table. I'm using a table variable #work here to simulate your existing table - just replace my table variable with your own table name:
DECLARE #work TABLE (display_order INT)
INSERT INTO #work VALUES(2)
INSERT INTO #work VALUES(4)
INSERT INTO #work VALUES(7)
INSERT INTO #work VALUES(10)
INSERT INTO #work VALUES(12)
SELECT * FROM #work
;WITH UpdateTable AS
(
SELECT
display_order, new_order = ROW_NUMBER() OVER (ORDER BY display_order)
FROM #work
)
UPDATE #work
SET display_order = u.new_order
FROM #work w
INNER JOIN UpdateTable u ON w.display_order = u.display_order
SELECT * FROM #work
Without CTE (but needs some key in the table)
declare #tbl table(id int primary key identity(1,1),Value int)
insert #tbl values(2)
insert #tbl values(5)
insert #tbl values(3)
select * from #tbl
select *, ROW_NUMBER() over(order by Value) from #tbl order by id
update #tbl set Value = result from #tbl tbl
inner join (select id, ROW_NUMBER() over(order by Value) result from #tbl ) hlp on tbl.id =hlp.ids
select * from #tbl