SQL statement to perform incremental updates based upon conditon - sql

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.

Related

Trying to update temporary table in sql by accumulating variable

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;

MS SQL - How to update local variable and have variable in WHERE condition?

currently I'm trying to update a local Variable using an UPDATE statement while also trying to cancel the UPDATE statement when the variable reaches a certain value:
UPDATE table
SET #var = #var + 1,
field = #var
WHERE #var < 10
This unfortunately doesn't work since it runs for all records instead of just 10. Has anyone an idea how to elegantly solve this without using a loop?
Thanks!
EDIT:
What I'm trying to do ist to allocate some kind of votes to parties. Say a party got 36.47% of the total votes. So I calculate a ratio of .47% (cutting of the integer part) for this party. Now I order my results table by ratio DESC and add one vote to each party as long as there are votes remaining. The remaining votes are stored in the variable. That's overly simplified but I hope you get what I want to do.
You can probably achieve what you're trying to do by using ROW_NUMBER(). Here's a basic example:
declare #t table (field int not null, Ord int not null)
insert into #t(field,Ord) values (0,1),(0,2),(0,3),(0,4),(0,5)
;With Numbered as (
select
*,
ROW_NUMBER() OVER (ORDER BY Ord) as rn
from
#t
)
update Numbered
set field = rn
where rn < 4
select * from #t
Results:
field Ord
----------- -----------
1 1
2 2
3 3
0 4
0 5
Here, the row numbers are being generated inside a CTE and using an appropriate column to make the ordering well-defined (as your edit suggests you have something similar available). We also take advantage that you can write an UPDATE against a CTE rather than the base table (provided the UPDATE clearly only attempts to update a single table)

Update existing schema using cursor

I'm trying change existing schema to add new column.
Here is my case - http://sqlfiddle.com/#!3/06c58/1
Value of Order column is int, which should represent order of items on UI from 1 to COUNT(Id) if I'm grouping TemplateId.
I see 2 possible solutions - make Order calculated field or use Cursor to update it.
Which one is better? And if update using cursor win -
May I know how to have such update ?
One way I can think of it is this:
Start a transaction
Insert into columns apart from Order
Update the table to set Order values
Commit transaction if everything is OK, else rollback.
You won't need to directly deal with cursors to do this, and the operation will be atomic in a way, since it's wrapped in a transaction block.
The update itself can be done something like this:
;with ord as
(Select id, row_number() over (partition by templateid order by selectedfieldid) rn from yourtable)
Update dbo.titlefields
Set order = rn - 1 --ROW_NUMBER() starts at 1 but we want to start at 0
From dbo.titlefields t inner join
ord x on t.id = x.id
Please let me know if I have understood your requirement correctly, and I will update my answer if that is not so.

My tricky SQL Update query not working so well

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

How to read the last row with SQL Server

What is the most efficient way to read the last row with SQL Server?
The table is indexed on a unique key -- the "bottom" key values represent the last row.
If you're using MS SQL, you can try:
SELECT TOP 1 * FROM table_Name ORDER BY unique_column DESC
select whatever,columns,you,want from mytable
where mykey=(select max(mykey) from mytable);
You'll need some sort of uniquely identifying column in your table, like an auto-filling primary key or a datetime column (preferably the primary key). Then you can do this:
SELECT * FROM table_name ORDER BY unique_column DESC LIMIT 1
The ORDER BY column tells it to rearange the results according to that column's data, and the DESC tells it to reverse the results (thus putting the last one first). After that, the LIMIT 1 tells it to only pass back one row.
If some of your id are in order, i am assuming there will be some order in your db
SELECT * FROM TABLE WHERE ID = (SELECT MAX(ID) FROM TABLE)
I think below query will work for SQL Server with maximum performance without any sortable column
SELECT * FROM table
WHERE ID not in (SELECT TOP (SELECT COUNT(1)-1
FROM table)
ID
FROM table)
Hope you have understood it... :)
I tried using last in sql query in SQl server 2008 but it gives this err:
" 'last' is not a recognized built-in function name."
So I ended up using :
select max(WorkflowStateStatusId) from WorkflowStateStatus
to get the Id of the last row.
One could also use
Declare #i int
set #i=1
select WorkflowStateStatusId from Workflow.WorkflowStateStatus
where WorkflowStateStatusId not in (select top (
(select count(*) from Workflow.WorkflowStateStatus) - #i ) WorkflowStateStatusId from .WorkflowStateStatus)
You can use last_value: SELECT LAST_VALUE(column) OVER (PARTITION BY column ORDER BY column)...
I test it at one of my databases and it worked as expected.
You can also check de documentation here: https://msdn.microsoft.com/en-us/library/hh231517.aspx
OFFSET and FETCH NEXT are a feature of SQL Server 2012 to achieve SQL paging while displaying results.
The OFFSET argument is used to decide the starting row to return rows from a result and FETCH argument is used to return a set of number of rows.
SELECT *
FROM table_name
ORDER BY unique_column desc
OFFSET 0 Row
FETCH NEXT 1 ROW ONLY
SELECT TOP 1 id from comission_fees ORDER BY id DESC
In order to retrieve the last row of a table for MS SQL database 2005, You can use the following query:
select top 1 column_name from table_name order by column_name desc;
Note: To get the first row of the table for MS SQL database 2005, You can use the following query:
select top 1 column_name from table_name;
If you don't have any ordered column, you can use the physical id of each lines:
SELECT top 1 sys.fn_PhysLocFormatter(%%physloc%%) AS [File:Page:Slot],
T.*
FROM MyTable As T
order by sys.fn_PhysLocFormatter(%%physloc%%) DESC
SELECT * from Employees where [Employee ID] = ALL (SELECT MAX([Employee ID]) from Employees)
This is how you get the last record and update a field in Access DB.
UPDATE compalints SET tkt = addzone &'-'& customer_code &'-'& sn where sn in (select max(sn) from compalints )
If you have a Replicated table, you can have an Identity=1000 in localDatabase and Identity=2000 in the clientDatabase, so if you catch the last ID you may find always the last from client, not the last from the current connected database.
So the best method which returns the last connected database is:
SELECT IDENT_CURRENT('tablename')
Well I'm not getting the "last value" in a table, I'm getting the Last value per financial instrument. It's not the same but I guess it is relevant for some that are looking to look up on "how it is done now". I also used RowNumber() and CTE's and before that to simply take 1 and order by [column] desc. however we nolonger need to...
I am using SQL server 2017, we are recording all ticks on all exchanges globally, we have ~12 billion ticks a day, we store each Bid, ask, and trade including the volumes and the attributes of a tick (bid, ask, trade) of any of the given exchanges.
We have 253 types of ticks data for any given contract (mostly statistics) in that table, the last traded price is tick type=4 so, when we need to get the "last" of Price we use :
select distinct T.contractId,
LAST_VALUE(t.Price)over(partition by t.ContractId order by created ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
from [dbo].[Tick] as T
where T.TickType=4
You can see the execution plan on my dev system it executes quite efficient, executes in 4 sec while the exchange import ETL is pumping data into the table, there will be some locking slowing me down... that's just how live systems work.
It is very simple
select top 10 * from TableName order by 1 desc
SELECT * FROM TABLE WHERE ID = (SELECT MAX(ID) FROM TABLE)
I am pretty sure that it is:
SELECT last(column_name) FROM table
Becaause I use something similar:
SELECT last(id) FROM Status