How to update top n rows dynamically? - sql

I have a table with similar rows...like
PartNo SerialNo Inven_Qty Status
------ -------- --------- ------
001A NULL 1 IN
001A NULL 1 IN
001A NULL 1 IN
001A NULL 1 IN
Now I want to update the rows dynamically..I have a web page where I enter PartNo and the value of items which are OUT...ex 2 items are OUT...I want to update 2 rows with Inven_Qty 0 and status as OUT....Can anyone please tell me how to do this???
Thanks in advance.

Based on Mikael Eriksson, for Oracle:
update YourTable
set Inven_Qty = 0,
Status = 'OUT'
where PartNo = '001A'
and Status = 'IN'
and rownum<=3
(for 3 items to update)

This syntax works for SQL Server. Might work for other DBMS as well.
update top (2) YourTable
set Inven_Qty = 0,
Status = 'OUT'
where PartNo = '001A' and
Status = 'IN'
Another way that may be more easily translated to a some other DBMS
with C as
(
select Inven_Qty,
Status,
row_number() over(order by (select 1)) as rn
from #T
where PartNo = '001A' and
Status = 'IN'
)
update C
set Inven_Qty = 0,
Status = 'OUT'
where rn <= 2

You can do it like this.
UPDATE table_name
SET Status = "OUT", Invent_QTY = 0,
WHERE PartNo = "<part number>" AND SerialNo = <serial number>

It would probably be better if you could use 'SerialNo' in the query, but if not you can try:
update <your table> set Status='OUT', Inven_Qty=0 where rowid in
(select rowid from <your table> where Status=IN and Inven_Qty=1
and PartNo=<part number> where rownum <= <some value>)
But this only works if you assume that Inven_Qty is either 1 or 0. If Inven_Qty can be greater than 1 I don't think you can even do this with just a single query.
EDIT: This won't work if SerialNo is null. You have to have some sort of unique id for this to work. If you don't you should add one. If you're working on oracle you can use ROWID.

Related

I'm trying to take a record from, for example row 1 and insert it into row 3

I have a field called RecordType that has three different records, 1, 2, 3. Each hold different records. I want to take the the balance from another field I have called Limit from RecordType 1 and insert it into RecordType 3 but I'm just unsure on how to do this. This will be going into a Crystal Report and I want to be able to suppress the RecordType 1 altogether.
I've tried a simple case statement but that's about it, I can't really think of any other ways to do it (I'm sure there's loads).
CASE
WHEN FA.RecordType = 3 THEN
FA.Limit
END AS LimitTest
Current results
Record Type
Limit
1
5,000,301
2
0
3
0
Expected Results
Record Type
Limit
2
0
3
5,000,301
You seem to want to combine the limit for types 1 and 3. You can do this with aggregation on an expression:
select (case when recordtype = 1 then 3 else recordtype end) as recordtype,
sum(limit) as limit
from t
group by (case when recordtype = 1 then 3 else recordtype end);
You can try using sub-query and a Case statement in your select statement, for example:
SELECT [RecordType],
(CASE [RECORDTYPE] WHEN 3 THEN
(SELECT LIMIT from Table_1 WHERE RECORDTYPE = 1)
ELSE LIMIT END) LimitTest
FROM TABLE_1 WHERE RECORDTYPE <> 1
You said:
Sorry my formatting is terrible I'm not sure how to do it properly. But to answer your question no type 1 & 3 will never have the same value as 3 never has a value. I want to basically move the value from type 1 into type 3
Which makes me think that this would be the simplest:
DELETE FROM table WHERE RecordType = 3
UPDATE table SET RecordType = 3 WHERE RecordType = 1
3 never has a value so let's get rid of them first, then 1 has the value but we want it to be 3 so just update all the 1s to be 3s instead
If you're not into deleting it, just mask it instead:
SELECT 3 as RecordType, Limit FROM table WHERE RecordType = 1
If you want to move value from type 1 to type 3 then do simple update in your query.
update t set t.value= t1.value from table as t , table as t1 where t.recordtype=3 and t1.recordtype=1
or
delete from table where recordtype = 3
update recordtype set recordtype=1 where recordtype=3
This will work may be
SELECT
IIF(A.RECORDTYPE = 1,3,A.RECORDTYPE) AS RECORDTYPE,
A.LIMIT
FROM
(
SELECT 1 RECORDTYPE,5000301 LIMIT UNION ALL
SELECT 2 RECORDTYPE,0 LIMIT UNION ALL
SELECT 3 RECORDTYPE,0 LIMIT
) A
WHERE A.RECORDTYPE IN (1,2)
ORDER BY RECORDTYPE
Check this if works for you.

SQL Group By and assign highest a value

I am struggling with the SQL (mssql) to manipulate my data as i need it. I have a table like this;
SOMEID, SOMEFIELD, DATE
5 True 01-01-2010
5 True 01-01-2011
5 False 05-05-2012
7 True 05-05-2011
7 False 06-07-2015
What I am trying to achieve is to add another column which assigns the value 1 if they are the most recent for that ID, and 0 if not. So in the above data example the new column values from top to bottom would be 0, 0, 1, 0, 1.
I know I need to group by date but am having trouble assigning the values.
Thanks for any pointers!
You can use row_number() in SQL Server like this:
select *
, case when (row_number() over (partition by SOMEID order by [Date] desc)) = 1 then 1 else 0 end seq
from
yourTable
order by
SOMEID, [Date];
SQL Fiddle Demo
You can use a self join to get the highest row per group then in update query use a case statement to assign value to new column
update a
set a.[somecol] = case when b.[SOMEID] is null then 1 else 0 end
from demo a
left join demo b on a.[SOMEID] = b.[SOMEID]
and a.[DATE] < b.[DATE]
DEMO
try this
SELECT SOMEID, SOMEFIELD, DATE
, CASE WHEN (SELECT MAX(SubTab.Date)
FROM myTable SubTab
WHERE SubTab.SOMEID = myTable.SOMEID
) = myTable.DATE
THEN 1 ELSE 0 END
FROM myTable

SQL check if the value is more than 4 then update the other column stop the updates

I I have one tables updating two columns if the second column the update more or equal to 4 set the other column to 0
Tried case statement .... but still not working please help!
update [dbo].[QueuedSms_TEST]
set issent = 0,pendingstatusid = pendingstatusid + 1
where sendresponse is null
while (select pendingstatusid from [dbo].[QueuedSms_TEST]) > 3
update [dbo].[QueuedSms_TEST]
set issent = -1
First you create a temporal query to get a row_number, and then update that with the required rules.
SQL Demo
WITH cte as (
SELECT *,
ROW_NUMBER() OVER (ORDER BY pendingstatusid) as rn
FROM QueuedSms_TEST
)
UPDATE cte
SET pendingstatusid = rn,
issent = CASE WHEN rn > 3
THEN -1
ELSE 0
END;

reward points and allocate those points in the original table's field

I have a table here :
I want to reward a gold and a silver(i.e a value of 1 wherever applicable,else 0 )to top 2 persons by looking at pointsRewarded field.
I already have the first table created .I have modified it with the extra fields that I want i.e rank,gold,silver fields.It has null values now.
i want the output to be something like this:
I have tried some query :
update dbo.original
set rnk = dense_rank() over (partition by WeekNumber order by pointsrewarded desc)
set gold =
case when rnk = '1' then 1 else 0 end
set silver =
case when rnk = '2' then 1 else 0 end
I already have modified the table design by adding the rnk,gold and silver fields.I want the values generated by the query to go and sit in those fields.
Please help me with the query or give me some suggestions on how to proceed.Please.
Thanks a lot.
This seems like a follow-up to your earlier question.
In SQL Server you can use an updatable CTE:
with toupdate as (
select o.*,
dense_rank() over (partition by WeekNumber order by pointsrewarded desc) as new_rnk
from dbo.original
)
update toupdate
set rnk = new_rank,
gold = (case when rnk = 1 then 1 else 0 end),
silver = (case when rnk = 2 then 1 else 0 end);
Note: Only use single quotes for string and date constants. Do not use single quotes for numeric constants.

insert values into a table's column and update that column

I want to insert values into a table's column and for every value inserted I want to copy all the rows `wHERE anotherColumn ='someString'
Then I want to update the id of the rows inserted based on the name they have (rN).
Table definition:
myFirstTable
rN rID rnk dateR value1 value2 calculation1 calculation2 calculation3
abc_3m 3 abc_3mxfx 20.10.2010 1 3 4 3 0.33
abc_6m 4 abc_6mxfx 20.10.2010 2 1 3 8 4
First, let's insert new values in rN. Values taken where rN = abc_6m
insert into #myFirstTable (rN)
values
('abc_6m'), ('abc_1y'), ('abc_2y'), ('abc_3y'), ('abc_4y'), ('abc_5y'), ('abc_7y'), ('abc_10y'), ('abc_15y'), ('abc_30y')
query 1
update #myFirstTable
set rN = (select * from #myFirstTable
where rN = 'abc_6m')
where rN in (
'abc_6m', 'abc_1y', 'abc_2y', 'abc_3y', 'abc_4y', 'abc_5y', 'abc_7y', 'abc_10y', 'abc_15y', 'abc_30y'
)
The table would become:
#myFirstTable
rN rID rnk dateR value1 value2 calculation1 calculation2 calculation3
abc_3m 3 abc_3mxfx 20.10.2010 1 3 4 3 0.33
abc_6m 4 abc_6mxfx 20.10.2010 2 1 3 8 4
abc_1y 4 abc_6mxfx 20.10.2010 2 1 3 8 4
abc_2y 4 abc_6mxfx 20.10.2010 2 1 3 8 4
and so on, for all the values inserted.
then i want to update the rID to the correct value so the column rID would look like this:
rN rID rnk dateR value1 value2 calculation1 calculation2 calculation3
abc_3m 3 abc_3mxfx 20.10.2010 1 3 4 3 0.33
abc_6m 4 abc_6mxfx 20.10.2010 2 1 3 8 4
abc_1y 5 abc_6mxfx 20.10.2010 2 1 3 8 4
abc_2y 6 abc_6mxfx 20.10.2010 2 1 3 8 4
In order to do so, I was thinking of writing something like this:
query 2
update #myFirstTable
set rID = (case when rnk = 'abc_1y' then rID = '100',
case when rnk = 'abc_2y' then rID = '101'
case when rnk = 'abc_3y' then rID = '102'
case when rnk = 'abc_4y' then rID = '103'
case when rnk = 'abc_5y' then rID = '104'
case when rnk = 'abc_7y' then rID = '105'
case when rnk = 'abc_10y' then rID = '106'
case when rnk = 'abc_15y' then rID = '107'
case when rnk = 'abc_30y' then rID = '108'
) end
select * from #myFirstTable
where rN = 'abc_6M'
Questions:
1. Is my logic correct for what I'm trying to achieve? (are query1 and query2 ok syntax wise? Can I write something like this in sql server 2012?
2. Is it ok to write an update column = (case when column = then another column = 'value' like that ?
3. Could I do this in a simpler way somehow using a window function?
ex:
select * from myTable
case (
when rN not in ('abc_1m', 'abc_3m', 'abc_6m') then
select * from #myFirstTable where rN like 'abc_6m'
over (partition by (select * from #myFirstTable where rN like 'abc_6m'))) end
Sorry if I'm not phrasing the question in the most clear way, but I am not sure what I could use and how to use it, that's why I'm looking for some guidence.
Thanks
EDIT:
I'm only a beginner and this is the best I could come up with, which seems to be what you want to do. Following steps are building up on the already existing table with the two rows called MyFirstTable.
1. step (inserting additional values in the rN column):
INSERT INTO MyFirstTable (rN)
VALUES ('abc_1y'),('abc_2y'),('abc_3y'),('abc_4y'),('abc_5y'),('abc_7y'),('abc_10y'),('abc_15y'),('abc_30y');
2. step (dropping rID column and creating a new one with auto_incremeneted values)
ALTER TABLE MyFirstTable
DROP COLUMN rID;
ALTER TABLE MyFirstTable
ADD rID int IDENTITY(3,1);
More info: http://www.w3schools.com/sql/sql_autoincrement.asp
3. step (updating fields in other columns with values from the 2nd row)
Here, the update is combined with something called "self-join", because the FROM clause doesn't allow us to use the same source table as the one that is being updated and so nested query to retrieve the desired value cannot be used.
UPDATE t1
SET
t1.rnk = t2.rnk,
t1.dateR = t2.dateR,
t1.value1 = t2.value1,
t1.value2 = t2.value2,
t1.calculation1 = t2.calculation1,
t1.calculation2 = t2.calculation2,
t1.calculation3 = t2.calculation3
FROM MyFirstTable t1
LEFT JOIN MyFirstTable t2 ON t2.rN='abc_6m'
WHERE t1.rN in ('abc_1y','abc_2y','abc_3y','abc_4y','abc_5y','abc_7y','abc_10y','abc_15y','abc_30y');
More info on self-join: https://technet.microsoft.com/en-us/library/ms177490%28v=sql.105%29.aspx
I found this answer to be helpful: https://stackoverflow.com/a/5574558/4296411
Warning: I'm really only a beginner and possibly none of the above may be considered a good practice and might contain mistakes leading to unpredictable results. :) It nevertheless seems to be answering your problem. Good luck!
EDIT2:
Well, this is most probably a ridiculous overkill, but since you cannot drop the rID column, I was able to come up with this rather complex solution. First, you would perform step #1, then the step#3 and then:
DECLARE #i INT = 1;
WHILE #i <= (SELECT COUNT(rN) FROM MyFirstTable WHERE rN IN ('abc_1y','abc_2y','abc_3y','abc_4y','abc_5y','abc_7y','abc_10y','abc_15y','abc_30y')) -- getting number of desired loops based on rows to be affected
BEGIN
UPDATE MyFirstTable
SET rID = 4+#i -- using number 4 as a starting point for incrementation and #i variable to perform the actual incrementation
WHERE
rN = ( -- specifying which row should be affected in each loop
SELECT SUBQUERY.rN
FROM ( -- assigning temporary row number for each desired row
SELECT ROW_NUMBER() OVER (ORDER BY value1) as row_num, rN -- using value1 in order to keep the current order (this doesn't seem to be a good practice, but it works)
FROM MyFirstTable
WHERE rN IN ('abc_1y','abc_2y','abc_3y','abc_4y','abc_5y','abc_7y','abc_10y','abc_15y','abc_30y')
) as SUBQUERY
WHERE SUBQUERY.row_num = #i
)
SET #i = #i + 1;
END;
PS: Please don't worry about my slight obsession with your problem. :D It's just that I consider this problem fun and It helps me to educate myself further.