Using ORDER BY command in an UPDATE SQL - sql

I am looking at updating an item number column from a number of rows in a table (which match a particular Product ID & type) but I want to order the rows by numbers in a 'Seqnumber' column then the item number column start at 1 and count each row sequentially by 1.
Using the code below I have been able to select the product id and type I want and update the item number column with sequentially increasing values, however I don't know how I can order the required rows?
DECLARE #id nvarchar(6)
SET #id = 0
UPDATE Table1
SET #id = Table1.ItemNumber = #id + 1
WHERE Product = '5486' AND Table1.Type = 'C'
I know you can't use the ORDER BY command within the UPDATE command without using it as a sub-query. But I'm not sure how I should include this in the above code?
I think I need to incorporate the code below but not sure what the SELECT statement should be and when I try I can't get it to work?
DECALRE #id nvarchar(6)
SET #id = 0
UPDATE Table1
SET #id = TABLE1.ItemNumber = #id + 1
FROM (SELECT TOP (??)* FROM Table1
WHERE Product = '5486' AND Table1.Type ='C'
ORDER BY Table1.SeqNumber ASC

You should be able to build a CTE with the values you want from the table and just update the CTE
declare #Table1 table (Product varchar(4), [Type] varchar(1), SeqNumber int, ItemNumber int)
INSERT INTO #Table1 VALUES
('5486', 'C', 3, 0),
('5486', 'C', 2, 0);
with cte as (
select *,
ROW_NUMBER() OVER (ORDER BY SeqNumber) rn
from #Table1
where Product = '5486' and Type ='C'
)
Update cte
set ItemNumber = rn

This should work:
SET #id = 0;
UPDATE Table1
SET #id = Table1.ItemNumber = (#id := #id + 1)
WHERE Product = 5486 and Table1.Type = 'C'
ORDER BY Table1.seqnumber;
You cannot use ORDER BY with a JOIN, so you need to initialize the variable before the update.

UPDATE sales_data
SET ID = ID + 1
ORDER BY ID DESC;

Related

SQL how to update the last row with a where conditon

Update table1 set status='open' where user='test' order by id DESC
i want to update the last row with a where conditon
You can use window function row_number() to get the first row in descending order of id.
with cte as
(
select *,row_number()over(order by id desc)rn from table1
)
Update cte set status='open' where user='test' and rn=1
Or you can use subquery to achieve same result:
UPDATE table1 SET status='open'
WHERE ID=(SELECT MAX(ID)FROM table1 where user='test') and user='test'
In order to find the record you want, you must first find the record you want and then change that record in the table. To do this, you need to create a temporary table and put the desired record in it, then update the table using the information obtained.
--Container to Insert Id which are to be iterated
Declare #temp1 Table
(
ID int
)
--Container to Insert records in the inner select for final output
Insert into #temp1
SELECT top 1 t.id FROM table1 t
WHERE t.user = 'test'
order by t.id desc
-- Keep track of #temp1 record processing
Declare #columnID int
Declare #columnValue varchar(100)
Begin
Set #columnID=(Select Top 1 id From #temp1)
Set #columnValue = 'open'
UPDATE table1 SET status = #columnValue WHERE id = #columnID
Delete #temp1 Where ID=#columnID
End
This should work, presume DBMS is MySQL
UPDATE table1
SET status = "open"
WHERE id in
(SELECT *
FROM
(SELECT id
FROM table1
WHERE USER = "test"
ORDER BY id DESC
LIMIT 1) tmp_tbl);

Update fetched rows in SQL Server

I have a stored procedure which looks like this:
alter procedure newProcedure
#take int,
#skip int
as
begin
set nocount on
declare #countRowNumbers int;
set #countRowNumbers = (select count(*) from TableA)
select *
from tableA a
order by a.ID
offset ISNULL(#skip,0) rows
fetch next ISNULL(#take, #countRowNumbers) rows only
--update only fetched rows (first 100, or second 100)
-- update TableA set Status = 2
end
I have column status which is representing if the row is under processing or not, so when I grab those 100 documents I need to update that Status status to 2.
How can I do that?
Combining the other answers, using an updatable CTE to carry out the update first, then using the output clause to capture the ID's updated and then select them to return.
declare #SelectedId table (id int);
with toupdate as (
select *
from tableA a
order by a.ID
offset isnull(#skip,0) rows
fetch next isnull(#take, #countRowNumbers) rows only
)
update toupdate
set [status] = 2
output Inserted.id into #SelectedId;
select *
from tableA
where ID in (select id from #SelectedId)
order by ID;
You should be able to use an updatable CTE for this:
with toupdate as (
select *
from tableA a
order by a.ID
offset ISNULL(#skip,0) rows
fetch next ISNULL(#take, #countRowNumbers) rows only
)
update toupdate
set status = 2;
alter procedure newProcedure
#take int,
#skip int
as
begin
set nocount on
declare #countRowNumbers int;
set #countRowNumbers = (select count(*) from TableA)
update tableA set status = 2 where ID in (
select a.ID
from tableA a
order by a.ID
offset ISNULL(#skip,0) rows
fetch next ISNULL(#take, #countRowNumbers) rows only )
--update only fetched rows (first 100, or second 100)
-- update TableA set Status = 2
end

Update of column values on condition

I wanted to update the column values on satisfying condition. I wanted the values to 1,2,3,4,5,...
I tried this query but its behaving in a strange way. I'm getting the values starting from 2 i.e 2,3,4,5,..
declare #id int;
set #id = 0;
UPDATE table
SET id = #id + 1, #id = #id + 1
WHERE col4 = 100
AND col5 = 500
AND col3 = 2
It seems like you want to enumerate records that meet the criteria specified in the WHERE clause. I would suggest using a CTE with ROW_NUMBER:
;WITH ToUpdate AS (
SELECT id,
ROW_NUMBER() OVER (ORDER BY col3) AS rn
FROM mytable
WHERE col4=100 AND col5=500 AND col3=2
)
UPDATE ToUpdate
SET id = rn
Try this -
Declare #id int;
Set #id=1;
UPDATE table
SET #id = id = #id + 1
WHERE
(col4=100 AND col5=500 AND col3=2)

Update int column in table with unique incrementing values

I am trying to populate any rows missing a value in their InterfaceID (INT) column with a unique value per row.
I'm trying to do this query:
UPDATE prices SET interfaceID = (SELECT ISNULL(MAX(interfaceID),0) + 1 FROM prices)
WHERE interfaceID IS null
I was hoping the the (SELECT ISNULL(MAX(interfaceID),0) + 1 FROM prices) would be evaluated for every row, but its only done once and so all my affected rows are getting the same value instead of different values.
Can this be done in a single query?
declare #i int = (SELECT ISNULL(MAX(interfaceID),0) + 1 FROM prices)
update prices
set interfaceID = #i , #i = #i + 1
where interfaceID is null
should do the work
DECLARE #IncrementValue int
SET #IncrementValue = 0
UPDATE Samples SET qty = #IncrementValue,#IncrementValue=#IncrementValue+1
simple query would be, just set a variable to some number you want.
then update the column you need by incrementing 1 from that number. for all the rows it'll update each row id by incrementing 1
SET #a = 50000835 ;
UPDATE `civicrm_contact` SET external_identifier = #a:=#a+1
WHERE external_identifier IS NULL;
For Postgres
ALTER TABLE table_name ADD field_name serial PRIMARY KEY
REFERENCE: https://www.tutorialspoint.com/postgresql/postgresql_using_autoincrement.htm
Assuming that you have a primary key for this table (you should have), as well as using a CTE or a WITH, it is also possible to use an update with a self-join to the same table:
UPDATE a
SET a.interfaceId = b.sequence
FROM prices a
INNER JOIN
(
SELECT ROW_NUMBER() OVER ( ORDER BY b.priceId ) + ( SELECT MAX( interfaceId ) + 1 FROM prices ) AS sequence, b.priceId
FROM prices b
WHERE b.interfaceId IS NULL
) b ON b.priceId = a.priceId
I have assumed that the primary key is price-id.
The derived table, alias b, is used to generated the sequence via the ROW_NUMBER() function together with the primary key column(s). For each row where the column interface-id is NULL, this will generate a row with a unique sequence value together with the primary key value.
It is possible to order the sequence in some other order rather than the primary key.
The sequence is offset by the current MAX interface-id + 1 via a sub-query. The MAX() function ignores NULL values.
The WHERE clause limits the update to those rows that are NULL.
The derived table is then joined to the same table, alias a, joining on the primary key column(s) with the column to be updated set to the generated sequence.
In oracle-based products you may use the following statement:
update table set interfaceID=RowNum where condition;
Try something like this:
with toupdate as (
select p.*,
(coalesce(max(interfaceid) over (), 0) +
row_number() over (order by (select NULL))
) as newInterfaceId
from prices
)
update p
set interfaceId = newInterfaceId
where interfaceId is NULL
This doesn't quite make them consecutive, but it does assign new higher ids. To make them consecutive, try this:
with toupdate as (
select p.*,
(coalesce(max(interfaceid) over (), 0) +
row_number() over (partition by interfaceId order by (select NULL))
) as newInterfaceId
from prices
)
update p
set interfaceId = newInterfaceId
where interfaceId is NULL
My table has 500 million records. The below code worked for me.
-- update rows using a CTE - Ervin Steckl
;WITH a AS(
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) as rn, id
FROM accounts2
)
UPDATE a SET id=rn
OPTION (MAXDOP 1)
https://www.mssqltips.com/sqlservertip/1467/populate-a-sql-server-column-with-a-sequential-number-not-using-an-identity/
You can try :
DECLARE #counter int
SET #counter = 0
UPDATE [table]
SET [column] = #counter, #counter = #counter + 1```

SQL Server 2000 : generating and incrementing data from column conditionally without using CURSOR

:)
Is there any way to create an index, and incrementing with a given condition, but without CURSOR handling/usage
For example:
The condition in my case is that: "if the current color (this is the item to be checked) is the same as the last one: not increment, otherwise increment in one unit"
This must be in a SQL query with no CURSOR USAGE and of course a good time (work with ... 10000 rows at least)
Thanks in advance.
EDIT: I forgot to mention that NEW_INDEX Column doesn't exist. It must be generated with the with the query.
EDIT2: Is there a way that only make use of SELECT/INSERT/UPDATE statements? (not set, declare...)
Assume a table called Colors with fields ID, Color, and ColorIndex of types int, varchar, and int respectively. I also assume the OP means prev / after based on an ordering of the ID field in asc order.
You could do this without a cursor, and use a while loop...but it definately isn't set based:
DECLARE #MyID int
DECLARE #CurrentIndex int
DECLARE #CurrentColor varchar(50)
DECLARE #PreviousColor varchar(50)
SET #CurrentIndex = (SELECT 0)
SET #MyID = (SELECT TOP 1 ID FROM Colors ORDER BY ID ASC)
SET #CurrentColor = (SELECT '')
SET #PreviousColor = (SELECT Color FROM Colors WHERE ID = #MyID)
WHILE (#MyID IS NOT NULL)
BEGIN
IF (#CurrentColor <> #PreviousColor)
BEGIN
SET #PreviousColor = (SELECT Color FROM Colors WHERE ID = #MyID)
SET #CurrentIndex = (SELECT #CurrentIndex + 1)
UPDATE Colors SET ColorIndex = #CurrentIndex WHERE ID = #MyID
END
ELSE
BEGIN
UPDATE Colors SET ColorIndex = #CurrentIndex WHERE ID = #MyID
SET #PreviousColor = (SELECT Color FROM Colors WHERE ID = #MyID)
END
SET #MyID = (SELECT TOP 1 ID FROM Colors WHERE ID > #MyID ORDER BY ID ASC)
SET #CurrentColor = (SELECT Color FROM Colors WHERE ID = #MyID)
END
The result after execution:
Performance wasn't too shabby as long as ID and color are indexed. The plus side is it is a bit faster then using a regular old CURSOR and it's not as evil. Solution supports SQL 2000, 2005, and 2008 (being that you are using SQL 2000 which did not support CTEs).
declare #ID int,
#MaxID int,
#NewIndex int,
#PrevCol varchar(50)
select #ID = min(ID),
#MaxID = max(ID),
#PrevCol = '',
#NewIndex = 0
from YourTable
while #ID <= #MaxID
begin
select #NewIndex = case when Colour = #PrevCol
then #NewIndex
else #NewIndex + 1
end,
#PrevCol = Colour
from YourTable
where ID = #ID
update YourTable
set NewIndex = #NewIndex
where ID = #ID
set #ID = #ID + 1
end
https://data.stackexchange.com/stackoverflow/q/122958/
select
IDENTITY(int,1,1) as COUNTER
,c1.ID
into
#temp
from
CUSTOMERS c1
left outer join (
select
c1.ID, max(p.ID) as PRV_ID
from
CUSTOMERS c1,
(
select
ID
from
CUSTOMERS
) p
where
c1.ID > p.ID
group by
c1.ID
) k on k.ID = c1.ID
left outer join CUSTOMERS p on p.ID = k.PRV_ID
where
((c1.FAVOURITE_COLOUR < p.FAVOURITE_COLOUR)
or
(c1.FAVOURITE_COLOUR > p.FAVOURITE_COLOUR)
or
p.FAVOURITE_COLOUR is null)
update
CUSTOMERS
set
NEW_INDEX = i.COUNTER
--select *
from
CUSTOMERS
inner join (
select
c1.ID, max(t.COUNTER) as COUNTER
from
CUSTOMERS c1,
(
select
ID
,COUNTER
from
#temp
) t
where
c1.ID >= t.ID
group by
c1.ID
) i on i.ID = CUSTOMERS.ID
drop table #temp
select * from CUSTOMERS