Get N th row value in sql server - sql

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

Related

SQL - how to update a column with each row value incremented by 1?

For the selected rows in a column, how to update each row sequentially from the beginning to the end, with each row value incremented by 1 (or certain number). I know this can be done in excel in few seconds but I could figure out how to achieve in SQL server. For instance:
customer id is NULL now
update customer id with every row incremented by 1 (i.e. first row = 1, second row = 2, .....nth row = n)
ship-to party customer id
0002018092 NULL
0002008127 NULL
0002000129 NULL
0002031592 NULL
0002034232 NULL
desired output
ship-to party customer id
0002018092 1
0002008127 2
0002000129 3
0002031592 4
0002034232 5
Also, for the selected rows in a column, how to update each row with the row number? I know there is a row_number() function but didn't succeed in producing the desired result. for instance
column A is NULL now
update Column A with every row incremented by 1 (i.e. first row = row number 1, second row = row number 2, .....nth row = row number n)
Any demonstration would be very helpful.thkans
example : suppose I want to add a value to each value in column SomeIntField in table tblUser
there are 2 ways of doing this easy
first: this just adds value 1 to each column SomeIntField
update tblUser set SomeIntField = SomeIntField + 1
second : this adds an incrementing value, the first row gets +1, second gets +2, and so on...
declare #number int = 0
update tblUser
set #number = #number + 1,
SomeIntField = isnull(SomeIntField, 0) + #Number
EDIT: based on your last comment this might be what you want
declare #table table (shiptoparty varchar(50), customer_id int)
insert into #Table (shiptoparty, customer_id)
values ('0002018092', NULL), ('0002008127', NULL), ('0002000129', NULL), ('0002031592', NULL), ('0002034232', NULL)
declare #number int = 0
update #table
set #number = #number + 1,
customer_id = isnull(customer_id, 0) + #Number
select * from #table
The result of this is :
shiptoparty | customer_id
----------- | -----------
0002018092 | 1
0002008127 | 2
0002000129 | 3
0002031592 | 4
0002034232 | 5
Rather than using a self referencing variable, use a CTE:
WITH CTE AS (
SELECT [Your Incrementing Column],
ROW_NUMBER() OVER (ORDER BY [Columns to Order By]) AS RN
FROM YourTable)
UPDATE CTE
SET [Your Incrementing Column] = RN;
Edit: To prove a point that ALL rows will be updated:
CREATE TABLE #Sample (String varchar(50),
IncrementingInt int);
INSERT INTO #Sample (String)
VALUES ('sdkfjasdf'),
('dfydsfdfg'),
('sdfgsdfg45yfg'),
('dfgf54d'),
('dsft43tdc'),
('f6gytrntrfu7m45'),
('5d6f45wgby54'),
('g34h636j'),
('jw'),
('h6nw54m'),
('g54j747jm5e5f4w5gsft'),
('ns67mw54mk8o7hr'),
('h45j4w5h4');
SELECT *
FROM #Sample;
WITH CTE AS(
SELECT IncrementingInt,
ROW_NUMBER() OVER (ORDER BY String) AS RN
FROM #Sample)
UPDATE CTE
SET IncrementingInt = RN;
SELECT *
FROM #Sample;
DROP TABLE #Sample;
GO
To update each row with row number
Try below
CREATE TABLE tmp(Id INT IDENTITY(1,1), Value INT)
INSERT INTO tmp(value) VALUES(1),(2),(3),(4),(5)
UPDATE T
SET
T.Value = B.RowNo
FROM tmp AS T
INNER JOIN (SELECT Id, ROW_NUMBER()OVER(ORDER BY Id) AS RowNo FROM tmp)AS B
ON T.Id = B.Id
Don't think very complex. Try the simple method given below
alter table table_name drop column customer_id
go
alter table table_name add id customer_id IDENTITY(1,1)
go
First problem:
you want to increase values in every row in certain column by 1 (or other nuber), try this:
update TABLE_NAME set column_to_increase = column_to_increase + 1
Second problem:
you want to get row number for only certain rows. Solution: first create column holding all row numbers, then get the rows:
select * from (
select column1, column2, ..., columnN, row_number() over (order by (select null)) as [rn] from MY_TABLE
) where *condition*
FYI: select null in over clause does exactly nothing, it's just there, because window functions (such as row_number) have to have over clause and some of them require order by.

Sql query to find the Most starting characters

Simplified scenario, I have a table with the following fields/values:
ID value
1 '12345'
2 '1234'
3 '123'
4 '12'
5 '1'
I want to find the record that is the closest to A='1230' and it should correspond to ID=3.
The only implementation I have in mind now is basic... Use a loop to iterate through A substring and do the comparison.
Is there a better way to solve this?
Will appreciate your help
Try this :-
Declare #valueToSearch int
Set #valueToSearch =1230
;WITH cte
AS
(
SELECT ID,RANK() OVER(ORDER BY ABS(value-#valueToSearch)) AS num FROM Sample
)
SELECT ID FROM cte
WHERE num=(SELECT MIN(num) FROM cte
This will give 2 as the result
Sql Fiddle
declare #q varchar(5)
select #q = '1230'
select top 1 number, substring(source.value, 1, number)
from master.dbo.spt_values, source
where type='p'
and number<=len(source.value)
and substring(source.value, 1, number) = substring(#q, 1, number)
order by number desc
Or using like...
select top 1 * from #source s
where #q like value +'%'
order by len(value) desc

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])

T-Sql count string sequences over multiple rows

How can I find subsets of data over multiple rows in sql?
I want to count the number of occurrences of a string (or number) before another string is found and then count the number of times this string occurs before another one is found.
All these strings can be in random order.
This is what I want to achieve:
I have one table with one column (columnx) with data like this:
A
A
B
C
A
B
B
The result I want from the query should be like this:
2 A
1 B
1 C
1 A
2 B
Is this even possible in sql or would it be easier just to write a little C# app to do this?
Since, as per your comment, you can add a column that will unambiguously define the order in which the columnx values go, you can try the following query (provided the SQL product you are using supports CTEs and ranking functions):
WITH marked AS (
SELECT
columnx,
sortcolumn,
grp = ROW_NUMBER() OVER ( ORDER BY sortcolumn)
- ROW_NUMBER() OVER (PARTITION BY columnx ORDER BY sortcolumn)
FROM data
)
SELECT
columnx,
COUNT(*)
FROM marked
GROUP BY
columnx,
grp
ORDER BY
MIN(sortcolumn)
;
You can see the method in work on SQL Fiddle.
If sortcolumn is an auto-increment integer column that is guaranteed to have no gaps, you can replace the first ROW_NUMBER() expression with just sortcolumn. But, I guess, that cannot be guaranteed in general. Besides, you might indeed want to sort on a timestamp instead of an integer.
I dont think you can do it with a single select.
You can use AdventureWorks cursor:
create table my_Strings
(
my_string varchar(50)
)
insert into my_strings values('A'),('A'),('B'),('C'),('A'),('B'),('B') -- this method will only work on SQL Server 2008
--select my_String from my_strings
declare #temp_result table(
string varchar(50),
nr int)
declare #myString varchar(50)
declare #myLastString varchar(50)
declare #nr int
set #myLastString='A' --set this with the value of your FIRST string on the table
set #nr=0
DECLARE string_cursor CURSOR
FOR
SELECT my_string as aux_column FROM my_strings
OPEN string_cursor
FETCH NEXT FROM string_cursor into #myString
WHILE ##FETCH_STATUS = 0 BEGIN
if (#myString = #myLastString) begin
set #nr=#nr+1
set #myLastString=#myString
end else begin
insert into #temp_result values (#myLastString, #nr)
set #myLastString=#myString
set #nr=1
end
FETCH NEXT FROM string_cursor into #myString
END
insert into #temp_result values (#myLastString, #nr)
CLOSE string_cursor;
DEALLOCATE string_cursor;
select * from #temp_result
Result:
A 2
B 1
C 1
A 1
B 2
Try this :
;with sample as (
select 'A' as columnx
union all
select 'A'
union all
select 'B'
union all
select 'C'
union all
select 'A'
union all
select 'B'
union all
select 'B'
), data
as (
select columnx,
Row_Number() over(order by (select 0)) id
from sample
) , CTE as (
select * ,
Row_Number() over(order by (select 0)) rno from data
) , result as (
SELECT d.*
, ( SELECT MAX(ID)
FROM CTE c
WHERE NOT EXISTS (SELECT * FROM CTE
WHERE rno = c.rno-1 and columnx = c.columnx)
AND c.ID <= d.ID) AS g
FROM data d
)
SELECT columnx,
COUNT(1) cnt
FROM result
GROUP BY columnx,
g
Result :
columnx cnt
A 2
B 1
C 1
A 1
B 2

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

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