Increment each field in a column by 1 - SQL Server 2008 - sql

I need to increment each field in a column by 1 starting from 2866. I've built the following query, but all it does is set each field to 2867 as opposed to 2868, 2869 etc...
DECLARE #a int
SET #a = 2866
UPDATE view_kantech_matched SET image_id = #a + 1
WHERE image_id = null
Any suggestions? Thanks

The general structure for doing this would be:
;WITH Numbered as (
SELECT *,ROW_NUMBER() OVER (ORDER BY <some column>) rn
FROM view_kantech_matched
WHERE image_id is NULL
)
UPDATE Numbered SET image_id = 2865 + rn
But I don't know what <some column> would be.

DECLARE #a int
SET #a = 2866
UPDATE view_kantech_matched SET image_id = #a, #a=#a + 1
WHERE image_id = null

If you want to update it to a value that starts at 2866 and increaments with every row you have to specify the column(s) to be used for the ordering.
Then you can use ROW_NUMBER:
WITH NoImageIDS AS
(
SELECT vkm.*, RN = ROW_NUMBER() OVER (ORDER BY AnyColumn ASC)
FROM dbo.view_kantech_matched vkm
WHERE image_id IS NULL
)
UPDATE NoImageIDS SET image_id = RN + 2866

Related

Update query with order by

I am trying to update one column based on another column short. I am using order by, but while using select top(10000) my incremental number going 4000 series but I need from 101, but initially I declare int 100
DECLARE #IncrementValue int
SET #IncrementValue = 100
UPDATE CabecDoc
SET CDU_NumberBook = #IncrementValue,
#IncrementValue = #IncrementValue + 1
FROM
(SELECT TOP(7000) *
FROM CabecDoc
WHERE data BETWEEN '2019-05-01' AND '2019-07-17'
AND Entidade = 'VD4'
AND tipodoc = 'VD' AND CDU_SimbolBook = '*'
ORDER BY NumDoc ASC) CabecDoc
I need update column from 101 to an incremental number through 7000 records.
Here's what you need. No need to declare variables.
UPDATE
CabecDoc
SET
CDU_NumberBook = 100 + RowNum
FROM
(
Select
top(7000) *,
ROW_NUMBER() OVER(
ORDER BY
NumDoc
) AS RowNum
FROM
CabecDoc
WHERE
data between '2019-05-01'
and '2019-07-17'
and Entidade = 'VD4'
and tipodoc = 'VD'
and CDU_SimbolBook = '*'
ORDER BY
RowNum ASC
) CabecDoc

Update rows starting for specific number

I have a number into variable like:
DECLARE #CurrentLastFolio INT = (SELECT TOP 1 Folio FROM myTable ORDER BY folio DESC)
So supposing we have number 1004 into this variable.
Into another query I have some rows with folio = 0:
SELECT * FROM myTable WHERE folio = 0
That I want to do is to update this records with #CurrentLastFolio + 1 on each row. So first row should have Folio = 1005, next 1006 and so on.
How can I achieve that?
You can use the following solution, updating the variable on the UPDATE too:
DECLARE #CurrentLastFolio INT = (SELECT MAX(folio) FROM table_name);
UPDATE table_name
SET folio = #CurrentLastFolio, #CurrentLastFolio += 1
WHERE folio = 0
demo on dbfiddle.uk
Arithmetic overflow error converting expression to data type int:
In case your values get larger than 2,147,483,647 (maximum value of INT data type) you need to use BIGINT intead of INT to store (column folio) or increment the value (variable #CurrentLastFolio):
-- you need to use BIGINT on the table.
CREATE TABLE table_name (
folio BIGINT
)
-- you need to use BIGINT on the variable.
DECLARE #CurrentLastFolio BIGINT = (SELECT MAX(folio) from table_name);
-- now you can count and store numbers larger than INT maximum value.
UPDATE table_name
SET folio = #CurrentLastFolio, #CurrentLastFolio += 1
WHERE folio = 0
demo on dbfiddle.uk
Check this:
declare #CurrentLastFolio int = (SELECT TOP 1 Folio from myTable order by folio desc);
with tbl AS
(
SELECT * ,ROW_NUMBER() OVER( order by c1 ) AS rn
FROM myTable
)
update tbl set folio = rn + #x
Example Implementation for easy understanding
create table t (c1 int);
GO
✓
insert into t values (1), (2), (3)
GO
3 rows affected
declare #x int = 1000;
with tbl AS
(
SELECT * ,ROW_NUMBER() OVER( order by c1 ) AS rn
FROM t
)
update tbl set c1 = rn + #x
GO
3 rows affected
select * from t
GO
| c1 |
| ---: |
| 1001 |
| 1002 |
| 1003 |
db<>fiddle here

Selecting data from table where sum of values in a column equal to the value in another column

Sample data:
create table #temp (id int, qty int, checkvalue int)
insert into #temp values (1,1,3)
insert into #temp values (2,2,3)
insert into #temp values (3,1,3)
insert into #temp values (4,1,3)
According to data above, I would like to show exact number of lines from top to bottom where sum(qty) = checkvalue. Note that checkvalue is same for all the records all the time. Regarding the sample data above, the desired output is:
Id Qty checkValue
1 1 3
2 2 3
Because 1+2=3 and no more data is needed to show. If checkvalue was 4, we would show the third record: Id:3 Qty:1 checkValue:4 as well.
This is the code I am handling this problem. The code is working very well.
declare #checkValue int = (select top 1 checkvalue from #temp);
declare #counter int = 0, #sumValue int = 0;
while #sumValue < #checkValue
begin
set #counter = #counter + 1;
set #sumValue = #sumValue + (
select t.qty from
(
SELECT * FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY id ASC) AS rownumber,
id,qty,checkvalue
FROM #temp
) AS foo
WHERE rownumber = #counter
) t
)
end
declare #sql nvarchar(255) = 'select top '+cast(#counter as varchar(5))+' * from #temp'
EXECUTE sp_executesql #sql, N'#counter int', #counter = #counter;
However, I am not sure if this is the best way to deal with it and wonder if there is a better approach. There are many professionals here and I'd like to hear from them about what they think about my approach and how we can improve it. Any advice would be appreciated!
Try this:
select id, qty, checkvalue from (
select t1.*,
sum(t1.qty) over (partition by t2.id) [sum]
from #temp [t1] join #temp [t2] on t1.id <= t2.id
) a where checkvalue = [sum]
Smart self-join is all you need :)
For SQL Server 2012, and onwards, you can easily achieve this using ROWS BETWEEN in your OVER clause and the use of a CTE:
WITH Running AS(
SELECT *,
SUM(qty) OVER (ORDER BY id
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS RunningQty
FROM #temp t)
SELECT id, qty, checkvalue
FROM Running
WHERE RunningQty <= checkvalue;
One basic improvement is to try & reduce the no. of iterations. You're incrementing by 1, but if you repurpose the logic behind binary searching, you'd get something close to this:
DECLARE #RoughAverage int = 1 -- Some arbitrary value. The closer it is to the real average, the faster things should be.
DECLARE #CheckValue int = (SELECT TOP 1 checkvalue FROM #temp)
DECLARE #Sum int = 0
WHILE 1 = 1 -- Refer to BREAK below.
BEGIN
SELECT TOP (#RoughAverage) #Sum = SUM(qty) OVER(ORDER BY id)
FROM #temp
ORDER BY id
IF #Sum = #CheckValue
BREAK -- Indicating you reached your objective.
ELSE
SET #RoughAverage = #CheckValue - #Sum -- Most likely incomplete like this.
END
For SQL 2008 you can use recursive cte. Top 1 with ties limits result with first combination. Remove it to see all combinations
with cte as (
select
*, rn = row_number() over (order by id)
from
#temp
)
, rcte as (
select
i = id, id, qty, sumV = qty, checkvalue, rn
from
cte
union all
select
a.id, b.id, b.qty, a.sumV + b.qty, a.checkvalue, b.rn
from
rcte a
join cte b on a.rn + 1 = b.rn
where
a.sumV < b.checkvalue
)
select
top 1 with ties id, qty, checkvalue
from (
select
*, needed = max(case when sumV = checkvalue then 1 else 0 end) over (partition by i)
from
rcte
) t
where
needed = 1
order by dense_rank() over (order by i)

Using ORDER BY command in an UPDATE 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;

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```