How to get the current row number in an SQL Server 2000 query? - sql

How do I get the row number in an SQL query using SQL Server 2000, where the ROW_NUMBER() function is not supported?

You can always try to use a temp table with an identity column
DECLARE #table TABLE(
[id] INT IDENTITY(1,1),
Val VARCHAR(10)
)
DECLARE #TableFrom TABLE(
Val VARCHAR(10)
)
INSERT INTO #TableFrom (Val) SELECT 'A'
INSERT INTO #TableFrom (Val) SELECT 'B'
INSERT INTO #TableFrom (Val) SELECT 'C'
INSERT INTO #TableFrom (Val) SELECT 'D'
INSERT INTO #table (Val) SELECT * FROM #TableFrom ORDER BY Val DESC
SELECT * FROM #table
Some of the best paging i have seen in Sql Server 2000 uses this pattern
DECLARE #PageStart INT,
#PageEnd INT
SELECT #PageStart = 51,
#PageEnd = 100
SELECT <TABLE>.*
FROM (
SELECT TOP (#PageStart - 1)
<ID>
FROM (
SELECT TOP (#PageEnd)
<ID>
FROM TABLE
ORDER BY <ID> ASC
) SUB
ORDER BY SUB.<ID> DESC
) SUB INNER JOIN
<TABLE> ON SUB.<ID> = <TABLE>.<ID>
ORDER BY SUB.<ID>

Another way to create a temp table with an identity to use:
SELECT Field1, Field2, IDENTITY(int, 1,1) AS MyID
INTO #Temp
FROM Table1

http://social.msdn.microsoft.com/Forums/en-US/transactsql/thread/13daeb85-da43-4166-b188-595a4a5d5282

You can't use Row_Number() in Sql Server 2000 - it was introduced in 2005.
In case you wanted to use Row_Number for paging, here are some ideas on how to perform efficient paging in Sql 2000:
Efficiently Paging Through Large Result Sets in SQL Server 2000
A More Efficient Method for Paging Through Large Result Sets

Another way of doing this without using a SQL defined function could be the following:
SELECT
(SELECT COUNT(1) + 1 FROM YourTable t2 WHERE t2.Id < t.Id) AS RowNumber
FROM YourTable t
It's a bit tricky, but seems simpler that the options that others gave you.

Could you elaborate how the below query will solve the problem?
SELECT ( SELECT SUM(1)
FROM specimen_source_ref
WHERE specimen_source_rcd <= reg.specimen_source_rcd
) AS 'Row Number'
,*
FROM
specimen_source_ref reg

Related

Loop through sql result set and remove [n] duplicates

I've got a SQL Server db with quite a few dupes in it. Removing the dupes manually is just not going to be fun, so I was wondering if there is any sort of sql programming or scripting I can do to automate it.
Below is my query that returns the ID and the Code of the duplicates.
select a.ID, a.Code
from Table1 a
inner join (
SELECT Code
FROM Table1 GROUP BY Code HAVING COUNT(Code)>1)
x on x.Code= a.Code
I'll get a return like this, for example:
5163 51727
5164 51727
5165 51727
5166 51728
5167 51728
5168 51728
This snippet shows three returns for each ID/Code (so a primary "good" record and two dupes). However this isnt always the case. There can be up to [n] dupes, although 2-3 seems to be the norm.
I just want to somehow loop through this result set and delete everything but one record. THE RECORDS TO DELETE ARE ARBITRARY, as any of them can be "kept".
You can use row_number to drive your delete.
ie
CREATE TABLE #table1
(id INT,
code int
);
WITH cte AS
(select a.ID, a.Code, ROW_NUMBER() OVER(PARTITION by COdE ORDER BY ID) AS rn
from #Table1 a
)
DELETE x
FROM #table1 x
JOIN cte ON x.id = cte.id
WHERE cte.rn > 1
But...
If you are going to be doing a lot of deletes from a very large table you might be better off to select out the rows you need into a temp table & then truncate your table and re-insert the rows you need.
Keeps the Transaction log from getting hammered, your CI getting Fragged and should be quicker too!
It is actually very simple:
DELETE FROM Table1
WHERE ID NOT IN
(SELECT MAX(ID)
FROM Table1
GROUP BY CODE)
Self join solution with a performance test VS cte.
create table codes(
id int IDENTITY(1,1) NOT NULL,
code int null,
CONSTRAINT [PK_codes_id] PRIMARY KEY CLUSTERED
(
id ASC
))
declare #counter int, #code int
set #counter = 1
set #code = 1
while (#counter <= 1000000)
begin
print ABS(Checksum(NewID()) % 1000)
insert into codes(code) select ABS(Checksum(NewID()) % 1000)
set #counter = #counter + 1
end
GO
set statistics time on;
delete a
from codes a left join(
select MIN(id) as id from codes
group by code) b
on a.id = b.id
where b.id is null
set statistics time off;
--set statistics time on;
-- WITH cte AS
-- (select a.id, a.code, ROW_NUMBER() OVER(PARTITION by code ORDER BY id) AS rn
-- from codes a
-- )
-- delete x
-- FROM codes x
-- JOIN cte ON x.id = cte.id
-- WHERE cte.rn > 1
--set statistics time off;
Performance test results:
With Join:
SQL Server Execution Times:
CPU time = 3198 ms, elapsed time = 3200 ms.
(999000 row(s) affected)
With CTE:
SQL Server Execution Times:
CPU time = 4197 ms, elapsed time = 4229 ms.
(999000 row(s) affected)
It's basically done like this:
WITH CTE_Dup AS
(
SELECT*,
ROW_NUMBER()OVER (PARTITIONBY SalesOrderno, ItemNo ORDER BY SalesOrderno, ItemNo)
AS ROW_NO
from dbo.SalesOrderDetails
)
DELETEFROM CTE_Dup WHERE ROW_NO > 1;
NOTICE: MUST INCLUDE ALL FIELDS!!
Here is another example:
CREATE TABLE #Table (C1 INT,C2 VARCHAR(10))
INSERT INTO #Table VALUES (1,'SQL Server')
INSERT INTO #Table VALUES (1,'SQL Server')
INSERT INTO #Table VALUES (2,'Oracle')
SELECT * FROM #Table
;WITH Delete_Duplicate_Row_cte
AS (SELECT ROW_NUMBER()OVER(PARTITION BY C1, C2 ORDER BY C1,C2) ROW_NUM,*
FROM #Table )
DELETE FROM Delete_Duplicate_Row_cte WHERE ROW_NUM > 1
SELECT * FROM #Table

How to execute this SQL Query

I am having following scenario
Drop Table #Temp
Create Table #Temp(name1 text, name2 text)
Insert INTO #Temp Values ('test','test')
Insert INTO #Temp Values ('test','test')
Insert Into #Temp1 Select * From
(
;With CTE as (
Select * from #Temp
)
select * from CTE
)
I know we can't use CTE as subquery .. but for hard time I don't know exact syntax of subquery since it is being provided by other system.
just image this
Insert Into #Temp1 Select * From
(
"Query Provided by Other System"
)
So I don't have any control on subquery ("Query Provided by Other System").. And I have also tried dynamic sql query like
Declare #subquery nvarchar(max)
set #subquery=';With CTE2 as ( Select * from #Temp) select * from CTE2'
INSERT INTO #Temp1 From (EXEC sp_executesql #subquery)
This also gives error...
More Things to know:
i)I don't know about what are the columns will sub query returns
ii)And I don't have any control in sub query . like what is syntax of subquery and how it looks like?
so from these things, even I can't use dynamic sql (EXEC sp_executesql).because I don't know what will happen if #subquery itself contains dynamic sql.
Please help anyone...
Use like this, with dynamic sql. It will work...
Insert Into #Temp1
EXEC sp_executesql #subquery
You can use the below syntax
;With CTE as (
Select * from #Temp
)
Insert Into #Temp1
Select *
From (
select * from CTE
) t
or if you don't have already created the #Temp1 table, use below code. It will automatically create the #temp1 table according to the selected fields
;With CTE as (
Select * from #Temp
)
Select *
Into #Temp1
From (
select * from CTE
) t
Besides syntax, you can simplify above SQL code as follows
;With CTE as (
Select * from #Temp
)
Insert Into #Temp1
Select *
From CTE
or better
Insert Into #Temp1
Select * from #Temp

DELETE EXCEPT TOP 1

Is there any way to delete all the rows in a table except one (random) row, without specifying any column names in the DELETE statement?
I'm trying to do something like this:
CREATE TABLE [dbo].[DeleteExceptTop1]([Id] INT)
INSERT [dbo].[DeleteExceptTop1] SELECT 1
INSERT [dbo].[DeleteExceptTop1] SELECT 2
INSERT [dbo].[DeleteExceptTop1] SELECT 3
SELECT * FROM [dbo].[DeleteExceptTop1]
DELETE
FROM [dbo].[DeleteExceptTop1]
EXCEPT
SELECT TOP 1 * FROM [dbo].[DeleteExceptTop1]
SELECT * FROM [dbo].[DeleteExceptTop1]
The final SELECT should yield one row (could be any of the three).
;WITH CTE AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT newid())) AS RN
FROM [dbo].[DeleteExceptTop1]
)
DELETE FROM CTE
WHERE RN > 1
Or similar to #abatishchev's answer but with more variety in the ordering and avoiding deprecated constructs.
DECLARE #C INT
SELECT #C = COUNT(*) - 1
FROM [dbo].[DeleteExceptTop1]
IF #c > 0
BEGIN
WITH CTE AS
(
SELECT TOP(#C) *
FROM [dbo].[DeleteExceptTop1]
ORDER BY NEWID()
)
DELETE FROM CTE;
END
Or a final way that uses EXCEPT and assumes no duplicate rows and that all columns are of datatypes compatible with the EXCEPT operator
/*Materialise TOP 1 to ensure only evaluated once*/
SELECT TOP(1) *
INTO #T
FROM [dbo].[DeleteExceptTop1]
ORDER BY NEWID()
;WITH CTE AS
(
SELECT *
FROM [dbo].[DeleteExceptTop1] T1
WHERE EXISTS(
SELECT *
FROM #T
EXCEPT
SELECT T1.*)
)
DELETE FROM CTE;
DROP TABLE #T
Try:
declare #c int
select #c = count(*) - 1 from [dbo].[DeleteExceptTop1]
IF #c > 0
BEGIN
set RowCount #c
delete from [dbo].[DeleteExceptTop1]
END
No.
You need to use a column name (such as that of the primary key) to identify which rows you want to remove.
"random row" has no meaning in SQL except its data. If you want to delete everything except some row, you must differentiate that row from the others you with to DELETE
EXCEPT works by comparing the DISTINCT values in the row.
EDIT: If you can specify the primary key then this is a trivial matter. You can simply DELETE where the PK <> your "random" selection or NOT IN your "random" selection(s).
EDIT: Apparently I'm wrong about the need to specify any column name, you can do it using the assigned ROW_NUMBER.. But I'm not going to delete my answer because it references your use of EXCEPT which was discussed in the comments. You cannot do it without deriving some column name like that from ROW_NUMBER
You could do something like this (SQL 2008)
DECLARE #Original TABLE ([Id] INT)
INSERT INTO #Original(ID) VALUES(1)
INSERT INTO #Original(ID) VALUES(2)
INSERT INTO #Original(ID) VALUES(3)
SELECT * FROM #Original;
WITH CTE AS
(SELECT ROW_NUMBER() OVER(ORDER BY ID) AS ROW, ID FROM #Original)
DELETE #Original
FROM #Original O
INNER JOIN CTE ON O.ID = CTE.ROW
WHERE ROW > 1
SELECT * FROM #Original
It seems like the simplest answer may be the best. The following should work:
Declare #count int
Set #count=(Select count(*) from DeleteExceptTop1)-1
Delete top (#count) from DeleteExceptTop1
I know it has been answered but what about?
DELETE
FROM [dbo].[DeleteExceptTop1]
Where Id not in (
SELECT TOP 1 * FROM [dbo].[DeleteExceptTop1])

Get N th row value in sql server

DECLARE #ActionNumber varchar(20)='EHPL-DES-SQ-1021'
set #ActionNumber=(select top 1 * from dbo.ANOSplit(#ActionNumber,'-')
order by ROW_NUMBER() OVER (ORDER BY items))
select #ActionNumber
from above query i need to return the 2ND and 3RD index from initial #ActionNumber
'EHPL-DES-SQ-1021' after Split().
format of the ActionNumber is exactly as above but DES, SQ and 1021 can change.
so i can not use ORDER BY items ASC or ORDER BY items DESC because it will order alphabetically.
above query returns 'EHPL'.how can i get DES and SQ.
You can do it with the ANOSplit function, but I would insert the result into a temp table or table variable.
As you said yourself, you can't just ORDER BY the values returned by the ANOSplit function because it will order alphabetically.
--> So you can use a temp table with an IDENTITY column, and use this for sorting:
DECLARE #ActionNumber varchar(20)='EHPL-DES-SQ-1021'
declare #tmp table
(
id int identity(1,1),
item varchar(20)
)
insert into #tmp (item)
select * from dbo.ANOSplit(#ActionNumber,'-')
select * from #tmp where id in (2,3)
The items will be inserted into the table in the exact order returned by the function, so after inserting you know that the lines with id 2 and 3 are the ones you want.
Try to use Substring with CharIndex >>>
DECLARE #ActionNumber varchar(20)='EHPL-DES-SQ-1021'
select SUBSTRING (#ActionNumber,CHARINDEX ('-',#ActionNumber,0) + 1, 3)
This isn't tested, but I think it will work:
DECLARE #ActionNumber varchar(20)='EHPL-DES-SQ-1021'
WITH nCTE AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY items) AS RNum
FROM dbo.ANOSplit(#ActionNumber,'-')
)
SELECT * FROM nCTE WHERE RNum = 2 --put n here

What is the easiest way to find a sql query returns a result or not?

Consider the following sql server query ,
DECLARE #Table TABLE(
Wages FLOAT
)
INSERT INTO #Table SELECT 20000
INSERT INTO #Table SELECT 15000
INSERT INTO #Table SELECT 10000
INSERT INTO #Table SELECT 45000
INSERT INTO #Table SELECT 50000
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER(ORDER BY Wages DESC) RowID
FROM #Table
) sub
WHERE RowID = 3
The result of the query would be 20000 ..... Thats fine as of now i have to find the result of this query,
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER(ORDER BY Wages DESC) RowID
FROM #Table
) sub
WHERE RowID = 6
It will not give any result because there are only 5 rows in the table.....
so now my question is
What is the easiest way to find a sql query returns a result or not?
Use ##ROWCOUNT > 0
So as a simple example,
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER(ORDER BY Wages DESC) RowID
FROM #Table
) sub
WHERE RowID = 6
IF ##ROWCOUNT > 0 BEGIN
RETURN 1
END
ELSE BEGIN
RETURN 0
END
For more information, here's a link to the documentation.
Like this:
SELECT ##rowcount