How to Create Identity field based on the row - sql

Using SQL Server 2005
Table1
Code ID (identity field)
001 1
001 2
002 1
003 1
003 2
How to create a identity field based on the code.
Need Query Help

Just like this:
ALTER TABLE dbo.YourTable
ADD NewColumn INT IDENTITY(1,1)
You can define the seed (starting value) as the first parameter, and the step (increments) as the second - so pick whatever makes sense to you; both seed=1 and step=1 seems to be the mostly used defaults.
The column will be added and populated with values when it's creatde.

It looks like you want to implement row_number() which will increment the id value based on the number of code values that you have:
select code, id
from
(
select code,
row_number() over(partition by code order by code) id
from yourtable
) d;
Using row_number() will allow you to calculate the value when you query the data in your table. See SQL Fiddle with Demo.
If you want to update your table with this value, then you could use something like the following:
;with cte as
(
select code, id,
row_number() over(partition by code order by code) rn
from yourtable
)
update cte
set id = rn;
See Demo.
Storing this value in your table will be difficult to maintain if you continue to add new rows for each code, it might be easier to implement the row_number() when you query the data.

Use ROW_NUMBER
SELECT
code,
ROW_NUMBER() OVER(PARTITION BY code ORDER BY code) AS ID
FROM Table1

(On rereading your question, I see that your id column is not unique, so it could not be an identity column.)
To create an identity field that uses initial values from the Code column, you could:
-- Create an empty copy of your table
select top 0 *
into CopiedTable
from YourTable;
-- Add an identity column
alter table CopiedTable add id int identity;
-- Copy the rows over, while initializing the identity column from Code
set identity_insert dbo.CopiedTable on
insert dbo.CopiedTable
(id, Code)
select Code
, Code
from dbo.YourTable;
set identity_insert dbo.CopiedTable off
-- Drop the old table
drop table dbo.YourTable
-- Rename the copied table
exec sp_rename 'CopiedTable', 'YourTable'

get it from count
DECLARE #ID int = (
SELECT COUNT(*) + 1 from test_1 WHERE [Code] = #CODE )

Related

Change value of duplicated rows

There is a table with tow columns(ID, Data) and there are 3 rows with same value.
ID Data
4 192.168.0.22
4 192.168.0.22
4 192.168.0.22
Now I want to change third row DATA column. In update SQL Server Generate an error that I ca not change the value.
I can delete all 3 rows. But I can not delete third row separately.
This table is for a software that I bought and I changed the third Server IP.
You can try the following query
create table #tblSimilarValues(id int, ipaddress varchar(20))
insert into #tblSimilarValues values (4, '192.168.0.22'),
(4, '192.168.0.22'),(4, '192.168.0.22')
Use Below query if you want to change all rows
with oldData as (
select *,
count(*) over (partition by id, ipaddress) as cnt
from #tblSimilarValues
)
update oldData
set ipaddress = '192.168.0.22_1'
where cnt > 1;
select * from #tblSimilarValues
Use Below query if you want to skip firs row
;with oldData as (
select *,
ROW_NUMBER () over (partition by id, ipaddress order by id, ipaddress) as cnt
from #tblSimilarValues
)
update oldData
set ipaddress = '192.168.0.22_2'
where cnt > 1;
select * from #tblSimilarValues
drop table #tblSimilarValues
You can find the live demo live demo here
Since there is no column that allows us to distinguish these rows from each other, there's no "third row" (nor a first or second one for that matter).
We can use a ROW_NUMBER function to apply arbitrary row numbers to these rows, however, and if we place that in a CTE, we can apply DELETE/UPDATE actions via the CTE and use the arbitrary row numbers:
declare #t table (ID int not null, Data varchar(15))
insert into #t(ID,Data) values
(4,'192.168.0.22'),
(4,'192.168.0.22'),
(4,'192.168.0.22')
;With ArbitraryAssignments as (
select *,ROW_NUMBER() OVER (PARTITION BY ID, Data ORDER BY Data) as rn
from #t
)
delete from ArbitraryAssignments where rn > 2
select * from #t
This produces two rows of output - one row was deleted.
Note that I say that the ROW_NUMBER is arbitrary. One of the expressions in both the PARTITION BY and ORDER BY clauses is the same. By definition, then, we know that no real ORDER is defined by this (because all rows within the same partition, by definition, have the same value for that expression).
In this case ID columns allows duplicate value which is wrong, ID should be unique.
Now what you can do is create a new column make that unique or Primary Key or change the duplicate values of ID column and make it Unique/Primary key.
Now as per your Unique key/Primary key you can update DATA column value by query as below:
UPDATE <Table Name>
SET DATA = 'new data'
WHERE ID = 3;

Unique ID using function with every record in Insert statement

I have a statement in stored procedure
INSERT into table(ID, name, age)
SELECT fnGetLowestFreeID(), name, age
FROM #tempdata
The function fnGetLowestFreeID() gets the lowest free ID of the table table.
I want to insert unique ID with every record in the table. I have tried iteration and transaction. But they aren't fitting the scenario.
I cannot use Identity Column. I have this restriction of using IDs between 0-4 and assigning the lowest free ID using that function. In case of returned ID greater than 4, the function is returning an error. Suppose there are already 1 and 2 in the table. The function will return 0 and I have to assign this ID to the new record, 3 to the next record and so on on the basis of number of records in the #tempdata.
try this
CREATE TABLE dbo.Tmp_City(Id int NOT NULL IDENTITY(1, 1),
Name varchar(50) , Country varchar(50), )
OR
ALTER TABLE dbo.Tmp_City
MODIFY COLUMN Id int NOT NULL IDENTITY(1, 1)
OR
Create a Sequence and assign Sequence.NEXTVAL as ID
in the insert statement
You can make use of a rank function like row_number and do something like this.
INSERT into table(ID, name, age)
SELECT row_number() over (order by id) + fnGetLowestFreeID(), name, age
FROM #tempdata
Here are 3 scenarios-
1)Show the function which you are using
2) Doesn't make sense to use a function and make it unique
still- you can use rank-
INSERT into table(ID, name, age)
SELECT row_number() over (order by id) + fnGetLowestFreeID(), name, age
FROM #tempdata
3)Else, get rid of function and use max(id)+1 because you dont want to use identitiy column
You could use a Numbers table to join the query doing your insert. You can google the concept for more info, but essentially you create a table (for example with the name "Numbers") with a single column "nums" of some integer type, and then you add some amount of rows, starting with 0 or 1, and going as far as you need. For example, you could end with this table content:
nums
----
0
1
2
3
4
5
6
Then you can use such a table to modify your insert, you don't need the function anymore:
INSERT into table(ID, name, age)
SELECT t2.nums, t.name, t.age
FROM (
SELECT name, age, row_number() over (order by name) as seq
FROM #tempdata
) t
INNER JOIN (
SELECT n.nums, row_number() over (order by n.nums) as seq
FROM Numbers n
WHERE n.nums < 5 AND NOT EXISTS (
SELECT * FROM table WHERE table.ID = n.nums
)
) t2 ON t.seq = t2.seq
Now, this query leaves out one of your requirements, that would be launching an error when no slots are available, but that is easy to fix. You can do previously a query and test if the count of records in table plus the sum of records in #tempdata is higher than 5. If so, you launch the error as you know there would not be enough free slots for the records in #tempdata.
Side note: table looks like a terrible name for a table, I hope that in your real code you have a meaningful name :)

Table valued Function - Identity(seed, increment)

I have a Table Valued Function qlikview_verlauf. I want to return a table with id, Date and Path.
Identity(seed, increment)
The ID is an autoincrement value. I want to start this autoincrement (seed) from the max(id)+1 from another table named Testfortschritt.
I have tried the following, but it doesn't work. The Error Message is incorrect Syntax.
Create FUNCTION [dbo].[qlikview_verlauf](#param INT)
RETURNS #qlikview_verlauf table (
ID INT IDENTITY((Select max(id) from Testfortschritt),1)
,[Date] date NOT NULL
,[Path] varchar(600) NOT NULL
)
I would set aside the IDENTITY of your ID column and rather use ROW_NUMBER to generate the ID in your SELECT statement.
For example:
SELECT
(SELECT MAX(id) FROM Testfortschritt) +
ROW_NUMBER OVER(ORDER BY (SELECT 1)) AS ID,
[Date],
[Path]
FROM <YourTable>
Since I don't know how your exact statement looks like, I used ORDER BY (SELECT 1) which lets SQL Server decide in which order records are numbered. If you have a specific order just replace (SELECT 1) with your order columns.
Since the ID should be uniqe I also omitted the PARTITION BY clause which isn't needed in your scenario.
More about ROW_NUMBER can be found here

remove duplicate records with a criteria

I am using a script which requires only unique values. And I have a table which has duplicates like below, i need to keep only unique values (first occurrence) irrespective of what is present inside the brackets.
can I delete the records and keep the unique records using a single query?
Input table
ID Name
1 (Del)testing
2 (Del)test
3 (Delete)testing
4 (Delete)tester
5 (Del)tst
6 (Delete)tst
So the output tables should be something like
Input table
ID Name
1 (Del)testing
2 (Del)test
3 (Delete) tester
4 (Del)tst
SELECT DISTINCT * FROM FOO;
It depends how much data you have to retrieve, if you only have to change Delete -> Del you can try with REPLACE
http://technet.microsoft.com/en-us/library/ms186862.aspx
also grouping functions should help you
I don't think this would be easy query
Assumption: The name column always has all strings in the format given in the sample data.
Try this:
;with cte as
(select *, rank() over
(partition by substring(name, charindex(')',name)+1,len(name)+1 - charindex(')',name))
order by id) rn
from tbl
),
filtered_cte as
(select * from cte
where rn = 1
)
select rank() over (partition by getdate() order by id,getdate()) id , name
from filtered_cte
How this works:
The first CTE cte uses rank() to rank the occurrence of the string outside brackets in the name column.
The second CTE filtered_cte only returns the first row for each occurence of the specified string. In this step, we get the expected results, but not in the desired format.
In this step we partition by and order by the getdate() function. This function is chosen as a dummy to give us continuous values for the id column while using the rank function as we did in step 1.
Demo here.
Note that this solution will return filtered values, but not delete anything in the source table. If you wish, you can delete from the CTE created in step 1 to remove data from the source table.
First use this update to make them uniform
Update table set name = replace(Name, '(Del)' , '(Delete)')
then delete the repetitive names
Delete from table where id in
(Select id from (Select Row_Number() over(Partition by Name order by id) as rn,* from table) x
where rn > 1)
First create the input date table
CREATE TABLE test
(ID int,Name varchar(20));
INSERT INTO test
(`ID`, `Name`)
VALUES
(1, '(Del)testing'),
(2, '(Del)test'),
(3, '(Delete)testing'),
(4, '(Delete)tester'),
(5, '(Del)tst'),
(6, '(Delete)tst');
Select Query
select id, name
from (
select id, name ,
ROW_NUMBER() OVER(PARTITION BY substring(name,PATINDEX('%)%',name)+1,20) ORDER BY name) rn
from test ) t
where rn= 1
order by 1
SQL Fiddle Link
http://www.sqlfiddle.com/#!6/a02b0/34

How to add row number column in SQL Server 2012

I'm trying to add a new column to an existing table, where the value is the row number/rank. I need a way to generate the row number/rank value, and I also need to limit the rows affected--in this case, the presence of a substring within a string.
Right now I have:
UPDATE table
SET row_id=ROW_NUMBER() OVER (ORDER BY col1 desc) FROM table
WHERE CHARINDEX('2009',col2) > 0
And I get this error:
Windowed functions can only appear in the SELECT or ORDER BY clauses.
(Same error for RANK())
Is there any way to create/update a column with the ROW_NUMBER() function? FYI, this is meant to replace an incorrect, already-existing "rank" column.
You can do this with a CTE, something like:
with cte as
(
select *
, new_row_id=ROW_NUMBER() OVER (ORDER BY col1 desc)
from MyTable
where charindex('2009',col2) > 0
)
update cte
set row_id = new_row_id
SQL Fiddle with demo.
If you are only updating a few thousand rows, you could try something like this:
select 'UPDATE MyTable SET ID = ' + CAST(RowID as varchar) + ' WHERE ID = ' + CAST(ID as varchar)
From (
select MyTable, ROW_NUMBER() OVER (ORDER BY SortColumn) RowID from RaceEntry
where SomeClause and SomeOtherClause
) tbl
Copy and paste the query results into the query editor and run. It's a bit sluggish and yukky bit it works.
Simple workaround would be to create a temp table that looks like
CREATE TABLE #temp (id int, rank int)
Where id is the same type as primary key in you main table.
Just use SELECT INTO to first fill temp table and then update from temp tableā€¦