I have a temp table that contains 4 variables that I need to do a calculation to and then accumulate that field from record to record, similar to a cumulative sum. I have setup a RANK in the #TEMP_TABLE_1. Here is my code:
UPDATE T1
SET T1.TOTAL_NET_BAL = ISNULL((SELECT T2.TOTAL_NET_BAL
FROM #TEMP_TABLE_1 AS T2
WHERE T1.RANK - 1 = T2.RANK),0) + (T1.MAX_STD_CAPACITY + T1.MAX_QT_CAPACITY) - (T1.STANDARD_PANELS + T1.QUICKTURN_PANELS)
FROM #TEMP_TABLE_1 AS T1
All this is doing is updating the current row in the table for TOTAL_NET_BAL. For some reason, it is not grabbing the amount when we are on the next row.
You're looking for a cumulative sum. You can see how to do a cumulative sum at this link and adapt that to fit your need.
So what I ended up doing was changing my code to another select statement into another TEMP table using the SUM function. Still don't know why my original SQL statement up top wouldn't work but I am able to move on. Thanks.
In SQL Server, you can use an updatable CTE. If I understand correctly, you want a running sum:
with toupdate as (TOTAL_NET_BAL) over
select t.*,
sum((T1.MAX_STD_CAPACITY + T1.MAX_QT_CAPACITY) - (T1.STANDARD_PANELS + T1.QUICKTURN_PANELS)) over (order by rank) as running_total
from #temp_table t
update toupdate
set total_net_bal = running_total;
Related
I am trying to create a sql update statement that will look for a company name sort their accompanying materials alphabetically then update another field in the table in increments of ten after setting a seed value.
The pseudocode sql I envision is something like this
#orderincrement = 100
Update Materials
Set Order = #orderincrenment + 10
where CompanyName = 'ThisCompany'
order by materials
Current Table Example:
What I want it to look like after:
It has been a while since I have done sql scripting.
Please provide any suggestions.
Use window functions and an updatable CTE:
with toupdate as (
select m.*,
row_number() over (partition by comapnyname order by materials) as seqnum
from materials m
)
update toupdate
set order = #orderincrement + 10 * seqnum
where companyname = ?;
I am guessing a bit on the actual arithmetic that you want, but whether you want to start at 10 in increments of 100 or at 100 in increments of 10, most of the query is the same.
I am trying to get the maximum value in a column based on another value in a row.
I have the following code :
UPDATE LeweringVsSkattingResultaat
SET maks = ((SELECT max(persentklaarkultivar2) FROM
LeweringVsSkattingResultaat)
group by kultivar2)
I get the following error :Incorrect syntax near the keyword 'group'.
I want the maksimum value in column persentklaarkultivar2 for each value in kultivar2.
Any help would be much appreciated.
Regards
Your subquery would generate an error if you have more than on value for kultivar2. The group by would return a row for each kultivar2.
Although you can use a correlated subquery to fix the problem (see end of answer), I like to do this with updatable CTEs and window functions:
with toupdate as (
select r.*,
max(persentklaarkultivar2) over (partition by kultivar2) as maxval
from LeweringVsSkattingResultaat r
)
update toupdate
set maks = maxval;
I should note that with window functions, you can readily calculate the maximum whenever you want, so it is not necessary to store it. Window functions are optimized so they can take advantage of an index on LeweringVsSkattingResultaat(kultivar2, persentklaarkultivar2).
This is probably a better approach. You won't have to figure out how to keep the maks value up-to-date when rows are inserted, updated, or deleted from the table.
The correlated subquery would look like:
UPDATE r
SET maks = (SELECT max(r2.persentklaarkultivar2)
FROM LeweringVsSkattingResultaat r2
WHERE r2.kultivar2 = r.kultivar2
)
FROM LeweringVsSkattingResultaat r;
Remove a ()
UPDATE LeweringVsSkattingResultaat
SET maks = ( SELECT max(persentklaarkultivar2) FROM
LeweringVsSkattingResultaat
group by kultivar2)
otherwise your group by is out the inner select
I tried to do an UPDATE statement with a random row from another table. I know this question has been asked before (here), but it doesn't seem to work for me.
I should update each row with a different value from the other table. In my case it only gets one random row from a table and puts that in every row.
UPDATE dbo.TABLE_CHARGE
SET COLRW_STREET =
(SELECT TOP 1 COLRW_STREET FROM CHIEF_PreProduction.dbo.TABLE_FAKESTREET
ORDER BY ABS(CHECKSUM(NewId())%250))
Thanks in advance!
I took a liberty to assume that you have ID field in your TABLE_CHARGE table. This is probably not the most efficient way, but seems to work:
WITH random_values as
(
SELECT t.id, t.COLRW_STREET, t.random_street FROM (
SELECT c.id, c.COLRW_STREET,
f.COLRW_STREET as random_street, ROW_NUMBER() OVER (partition by c.id ORDER BY ABS(CHECKSUM(NewId())%250)) rn
FROM table_charge c, TABLE_FAKESTREET f) t
WHERE t.rn = 1
)
UPDATE random_values SET COLRW_STREET = random_street;
SQL Fiddle demo
Your original code did not work because when yo do ... SET x = (SELECT TOP 1 ..) database does OUTER JOIN of your target table with one TOP row, which means that one single row is applied to all rows in your target table. Hence you have same value in all rows.
Following query demonstrates what is happening in the UPDATE:
SELECT * FROM
TABLE_CHARGE tc,
(SELECT TOP 1 COLRW_STREET as random_street FROM TABLE_FAKESTREET
ORDER BY ABS(CHECKSUM(NewId())%250)) t
My solution gets all fake records ordered randomly for each record in target table and only selects the first one per ID.
I have a query that allows me to get records from a database table by giving it a minimum and maximum limit.
It goes like this:
SELECT T1.CDUSUARIO, T1.DSALIAS, T1.DSNOMBRE_EMPRESA, T1.DSCARGO, T1.DSDIRECCION_CORREO, T1.CDUSUARIO_ADMINISTRADOR, T1.FEMODIFICACION
FROM (SELECT *,
ROW_NUMBER() OVER (ORDER BY CDUSUARIO) as row FROM TBL_USUARIOS ) as T1
WHERE row > #limiteInf
and row <= #limiteSup
ORDER BY DSALIAS ASC;
Now, it works like heaven on SQL Server 2005 and SQL Server 2008 but tried to run it on an SQL Server 2000 database and says:
ROW_NUMBER it's an unknown function name or something like that.
What can I do??
There is a COUNT(*) with SELF JOIN solution here that will scale badly
You can load a temp table with an IDENTITY column and read back but it's not guaranteed to work (can't find article on it, was told at an MS Seminar years ago)
Neither solution will support PARTITION BY
I've not mentioned loop or CURSOR based solutions which are probably worse
Edit 20 May 20011
Example demo of why IDENTITY won't work: Do Inserted Records Always Receive Contiguous Identity Values
I know this thread is bit old, but for anyone else looking for same solution, I think it will be useful to know that there is a good solution for this problem.
Please see the original link here
For those who do not want to click on the link, I have copied and pasted the code below. Again, credit goes to original publisher
Here is the below SQL for SQL Server 2000 to select the latest version of a record grouping by a single column.
SELECT *
FROM (
SELECT *, (
SELECT COUNT(*)
FROM MyTable AS counter
WHERE counter.PartitionByColumn = MyTable.PartitionByColumn
AND counter.OrderByColumn >= MyTable.OrderByColumn
) AS rowNumber
FROM MyTable
) AS r1
WHERE r1.rowNumber = 1
Same code in SQL Server 2005 would look like this:
SELECT * FROM (SELECT *, ROW_NUMBER() OVER(PARTITION BY PartitionByColumn
ORDER BY OrderByColumn DESC) AS rowNumber FROM MyTable) AS rw1
WHERE rw1.rowNumber = 1
Use another function or upgrade your database. ROW_NUMBER did not exist back in the 2000 version of the database. Point. Nothing you can do about it.
This is my solution to the problem:
declare #i int
declare #t table (row int, stuff varchar(99))
insert into #t
select 0,stuff from mytable -- <= your query
set #i=0
update #t set row=#i, #i=#i+1
select * from #t
Explanation:
create a memory table
insert data (your query) with the row number as 0
update the row number field with an int variable which is incremented in the same update for the next record (actually the variable is incremented first and then updated, so it will start from 1)
"select" the result from the memory table.
You may ask, why don't i use the variable in the select statement? It would be simpler but it's not allowed, only if there is no result. It's ok to do it in an update.
I am trying to update a table in my database with another row from another table. I have two parameters one being the ID and another being the row number (as you can select which row you want from the GUI)
this part of the code works fine, this returns one column of a single row.
(SELECT txtPageContent
FROM (select *, Row_Number() OVER (ORDER BY ArchiveDate asc) as rowid
from ARC_Content Where ContentID = #ContentID) as test
Where rowid = #rowID)
its just when i try to add the update/set it won't work. I am probably missing something
UPDATE TBL_Content
Set TBL_Content.txtPageContent = (select txtPageContent
FROM (select *, Row_Number() OVER (ORDER BY ArchiveDate asc) as rowid
from ARC_Content Where ContentID = #ContentID) as test
Where rowid = #rowID)
Thanks for the help! (i have tried top 1 with no avail)
I see a few issues with your update. First, I don't see any joining or selection criteria for the table that you're updating. That means that every row in the table will be updated with this new value. Is that really what you want?
Second, the row number between what is on the GUI and what you get back in the database may not match. Even if you reproduce the query used to create your list in the GUI (which is dangerous anyway, since it involves keeping the update and the select code always in sync), it's possible that someone could insert or delete or update a row between the time that you fill your list box and send that row number to the server for the update. It's MUCH better to use PKs (probably IDs in your case) to determine which row to use for updating.
That said, I think that the following will work for you (untested):
;WITH cte AS (
SELECT
txtPageContent,
ROW_NUMBER() OVER (ORDER BY ArchiveDate ASC) AS rowid
FROM
ARC_Content
WHERE
ContentID = #ContentID)
UPDATE
TC
SET
txtPageContent = cte.txtPageContent
FROM
TBL_Content TC
INNER JOIN cte ON
rowid = #rowID