SQL - Update same table based on a condition in WHERE - sql

I have a requirement to write an SP something like below. This SP is called every second from a .net windows service app.
SELECT TOP 1 ID
FROM TABLE
WHERE GETDATE() < ExpirationDate
ORDER BY ID
If GetDate() > ExpirationDate update the record column with a value.
I do not want to do the below as every time the SP is called, it looks at the whole table for update.
I only want to update the record the SP is currently looking at.
UPDATE [TableName]
SET fiel1=1 , field2 = 'abc'
WHERE ExpirationDate > GETDATE()
Thanks in advance.

Use an Update/Select. Depending upon how your SQL instance is configured, you might have to wrap the inner select with the second example below
UPDATE [TableName] SET [TableName].fiel1= 1 , [TableName].field2 = 'abc'
FROM (
SELECT TOP 1 ID
FROM TABLE
WHERE GETDATE() < ExpirationDate
ORDER BY ID
) a
where [TableName].ID = a.ID
Might have to try this:
UPDATE [TableName] SET [TableName].fiel1= 1 , [TableName].field2 = 'abc'
FROM (
SELECT TOP 100 PERCENT * FROM (
SELECT TOP 1 ID
FROM TABLE
WHERE GETDATE() < ExpirationDate
ORDER BY ID
) b
) a
where [TableName].ID = a.ID

This will update the single row value you return in your original script:
UPDATE [table]
SET
Field1 = 1,
Field2 = abc
WHERE ID =
(
SELECT MIN(ID)
FROM [table]
WHERE GETDATE() < ExpirationDate
)

Related

max latest null value sql

I am experiencing the following problem. I have a table in this table I same history. Due to an error, I'm interested in finding the following information.
The latest record for a user where column1 value is null and the modifiedon date is the newest for this user. The problem is the table contains more records where the modifiedon is not null for this user and mutated after the date I'm looking for.
Can someone please point me in the right direction?
Sample data:
personid FreeField01 ModifiedOn
1 0004998 15-10-2019 11:48:19
1 NULL 20-10-2019 01:53:39
1 0004998 22-10-2019 14:58:44
1 0004998 22-10-2019 14:58:44
1 NULL 23-10-2019 07:52:46
1 0004998 23-10-2019 17:16:45
So for this user, I'm not interested in any record and should be excluded from the result because the modified on datetime should be before 29-10 and before that date the freefield01 value should be null and modifiedon should be the latest.
Three conditions:
There is no newer entry for the person.
The entry value is NULL.
The date is before 2019-10-29.
The query:
select *
from mytable
where not exists
(
select *
from mytable newer
where newer.personid = mytable.personid
and newer.modifiedon > mytable.modifiedon
)
and freefield01 is null
and modifiedon < date '2019-10-29'
order by personid;
You can use this below script-
WITH CTE
AS(
SELECT personid,MAX(ModifiedOn) MD
FROM your_table
GROUP BY personid
HAVING MAX(ModifiedOn) < '30-10-2019'
)
SELECT * FROM your_table A
INNER JOIN CTE B ON A.personid = B.personid
AND A.ModifiedOn = B.MD
AND A.FreeField01 IS NULL
DEMO HERE
If I understand correctly, you are looking for persons where the FreeField01 has a value of NULL as of a certain date.
Here is one method:
select t.*
from t
where t.ModifiedOn = (select max(t2.ModifiedOn)
from t t2
where t2.personid = t.personid and
t2.ModifiedOn <= '2019-10-29'
) and
t.FreeField01 is null;
EDIT:
Based on your comment, you might just want an aggregation and having:
select personid
from t
where t.ModifiedOn <= '2019-10-29'
group by person_id
having sum(case when t.FreeField01 is null then 1 else 0 end) = 0
The simplest query that I found might be the following if I understand your request well :
SELECT t.personid, t.FreeField01, MAX(ModifiedOn) FROM test t
GROUP BY personid
HAVING MAX(ModifiedOn) < '29-10-2019' AND FreeField01 IS NULL
SEE EXAMPLE HERE
EDIT : Following below suggestions you can use this query instead :
SELECT t1.personid, t1.FreeField01, t1.ModifiedOn
FROM test t1
JOIN (
SELECT t.personid, MAX(ModifiedOn) AS MaxModifiedOn FROM test t
GROUP BY personid
HAVING MAX(ModifiedOn) < STR_TO_DATE('29-10-2019','%d-%m-%Y')
) t2 ON (t1.personid = t2.personid AND t1.ModifiedOn = t2.MaxModifiedOn)
WHERE FreeField01 IS NULL
SEE NEW DEMO HERE

SQL Logic - logic involving Update statement with Group By clause

Trying SQL after a long time.
Need you help to solve this task.
I have created a Procedure for updating a column's values from row 1 to N based on other Column combinations.
Currently, other columns are populated and the calculated column is null
Ex:
Account Category Metric Count Calculated Cloumn 5
A 1 ABC 45
A 1 DEF 25
A 1 XYZ
B 5 ABC 29
B 5 DEF
In above table Calculated Column 5 is the field in Focus that is to be calculated using combination of first 4 fields,
ex:
if Account=a ,Category=1 and metric -abc,def,xyz then
sum(count) Group by Account and Category
Different logics for different combination.
Now i am using below procedure script:
SET #variable1 = (select sum(count)
from table1
where [Category] = '1'
and [ACCOUNT] = 'A'
and [Metric Name] = 'ABC' );
SET #variable2 = 'select sum(count)
from table1
where [Category] = '1'
and [ACCOUNT] = 'B'
and [Metric Name] = 'DEF' ';
update [dbo].[table1]
set calculated field = (
(case when
#variable1 > '0'
then
#variable1
else
#variable2
end)
Problem with this script is that the Output value is replicated across all the rows rather than just for that combination.
Basically i need to use Group by Account and Category column for calculated field so that output values are reflected only for that combination.
try this :
UPDATE [dbo].[table1]
SET calculated field = (
(CASE WHEN
#variable1 > '0'
THEN
#variable1
ELSE
#variable2
END)
WHERE [Category] = '1'
AND [ACCOUNT] = 'A'
AND [Metric Name] = 'ABC'
I am assuming SQL Server based on the syntax.
I don't think variables are the right approach. For the information you have provided:
with toupdate as (
select t.*,
sum(count) over (partition by Account, Category) as sum_1
from t
)
update toupdate
set calculated_field = sum_1
where Account = 'A' and Category = 1 and metric in ('abc', 'def', 'xyz);

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

Select statement to return constant when no records found in table in SQL Server 2008

I am have a table with data and now i need to return zero in select statement if there is no records in table for example. I need to use it in Stored Procedure.
-- If no records exists in below select statement
SELECT ID,Text,Date FROM tblData WHERE ID = 12
IF (##ROWCOUNT = 0)
BEGIN
SELECT -5 AS ID
END
Output:
ID Text Date
ID
-5
Expected output
ID
-5
If you want to return 1 row even when there is no match, you can use aggregation:
SELECT (CASE WHEN COUNT(*) = 0 THEN -5 ELSE MAX(ID) END) as ID
FROM tblData
WHERE ID = 12;
I always use an Exists statment.
if exists(SELECT ID FROM tblData WHERE ID = 12)
select 0 as RowsExist
else
select 1 as RowsExist
For a single scalar value you could use something like;
SELECT ISNULL((SELECT ID FROM tblData WHERE ID = 12), 0) as ID
Rhys
SELECT (CASE WHEN Ta.ID IS NULL THEN TBL.ID
ELSE Ta.ID END) AS ID,Ta.Text,Ta.Date
FROM (VALUES(-5)) AS TBL(ID)
LEFT JOIN
(
SELECT ID,Text,Date FROM tblData WHERE ID = 12
)
AS Ta ON Ta.ID = Ta.ID

How to update top n rows dynamically?

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.