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ā¦
Related
I have data in a view where the Col_Head column values are supposed to be column headers(they are constant for every sequence of data from 1-8.
And Value column entries need to come as row values.
I need to write some SQL that transposes/pivots rows from Col_Head as column headers.
Example:
Expected data:
If you had a specific Id for each person then you didn't need to create CTE, any way
First, I create specific Id for each person like this via CTE:
/*Create CTE*/
With tempTable as
(
select
row_number() over( order by(select 0) ) row_num,
*
from myTable
),newTable as(
select
case when (row_num %8)>0 then (row_num /8)+1 else (row_num /8) end sp_Id,
*
from tempTable
)
/*MainQuery*/
select
*
from (select sp_id, Col_Header,[Value] from newTable )as temp
pivot
(
max([Value])
for Col_Header in ([Emp name],[Emp Dept],[Emp Grade],[Emp class],[Emp Sal],[Emp manager],[Emp Date of join],[Emp documents])
) pivotTable
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;
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
I was wondering is there a way to retrieve, for example, 2nd and 5th row from SQL table that contains 100 rows?
I saw some solutions with WHERE clause but they all assume that the column on which WHERE clause is applied is linear, starting at 1.
Is there other way to query a SQL Server table for a specific rows in case table doesn't have a column whose values start at 1?
P.S. - I know for a solution with temporary tables, where you copy your select statement output and add a linear column to the table. I am using T-SQL
Try this,
SELECT * FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY ColumnName ASC) AS rownumber
FROM TableName
) as temptablename
WHERE rownumber IN (2,5)
With SQL Server:
; WITH Base AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY id) RN FROM YourTable
)
SELECT *
FROM Base WHERE RN IN (2, 5)
The id that you'll have to replace with your primary key or your ordering, YourTable that is your table.
It's a CTE (Common Table Expression) so it isn't a temporary table. It's something that will be expanded together with your query.
There is no 2nd or 5th row in the table.
There is only the 2nd or 5th result in a resultset that you return, as determined by the order you specify in that query.
If you are on SQL Server 2005 or above, you could use Row_Number() function. Ex:
;With CTE as (
select col1, ..., row_number() over (order by yourOrderingCol) rn
from yourTable
)
select col1,...
from cte
where rn in (2,5)
Please note that yourOrderingCol will decide the value of row number (i.e. rn).
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 )