SQL - Execute two update queries at one time - sql

I am trying to allocate a value from one table into another table using an update script.
This works fine for one record with a matching possibility
UPDATE Template_Survey
SET K2ref = tbAsset.AssetNo
FROM Template_Structure_Location INNER JOIN
Template_Survey ON
Template_Structure_Location.TEMPLATE_STRUCTURE_LOCATION_REF = Template_Survey.TEMPLATE_STRUCTURE_LOCATION_REF INNER JOIN
tbAsset ON Template_Structure_Location.RoomID = tbAsset.LocationID AND Template_Structure_Location.RoomID = tbAsset.LocationID
WHERE K2transferNote ='Reallocate - same no of spare items' and (tbAsset.AssetName = 'Archive or re-use') and (TEMPLATE_SURVEY_REF = 4369 or TEMPLATE_SURVEY_REF = 4405)
and (Template_Survey.K2ref = 0 OR
Template_Survey.K2ref IS NULL)
but if there are two records in Template_Survey table and in the tbAsset table that match the criteria, the first record found in the tbAsset table is used as the value against both records in the Template_Survey table.
When there is just one possible record I run a second query to update the tbAsset.AssetName value so that that record can no longer be found by the previous query eg
UPDATE tbAsset
SET tbAsset.AssetName = 'Reallocated to item in same location-needs update'
WHERE (AssetNo IN
(SELECT K2Ref
FROM Template_Survey)) and (tbAsset.AssetName = 'Archive or re-use')
How do I write something that will do the first query for one record and then the second query for the corresponding record before repeating the process so that a distinct record is found each time?
Thanks in advance. Sorry if it doesn't make much sense, it's really hard to explain.

Related

Update foreign keys to one column for all records in table

I have the following query:
UPDATE D00EMA01.EMA_SUMO_CM_MEMBER sm
SET sm.SUBSCRIPTION_ID =
(SELECT sb.SUBSCRIPTION_ID
FROM D00EMA01.EMA_SUMO_SUBSCRIPTION_MIRROR sb
WHERE sb.SUBSCRIPTION_NUMBER = sm.MEMBER_NUMBER);
It is a simple update statement where I want to update the sequence PK of table EMA_SUMO_SUBSCRIPTION_MIRROR to about 300k records in table EMA_SUMO_CM_MEMBER.
Currently this column is null for all records.
The query runs for a very long time, and eventually times out, and nothing seems to be happening with a large set of rows.
What is the more performant way to get the desired result?
How about merge?
merge into d00ema01.ema_sumo_cm_member sm
using d00ema01.ema_sumo_subscription_mirror sb
on (sb.subscription_number = sm.member_number)
when matched then update set
sm.subscription_id = sb.member_number;
Make sure sb.subscription_number and sm.member_number are indexed.
Do not use a sub query, it is very slow
In general, you can change and increase the time out for the execution of the query
When the time out expires and the query fails, all records return to their state before the query
Try this
UPDATE sm
SET sm.SUBSCRIPTION_ID = sb.SUBSCRIPTION_ID
from D00EMA01.EMA_SUMO_CM_MEMBER sm
inner join D00EMA01.EMA_SUMO_SUBSCRIPTION_MIRROR sb
on sb.SUBSCRIPTION_NUMBER = sm.MEMBER_NUMBER

Request optimisation

I have two tables, on one there are all the races that the buses do
dbo.Courses_Bus
|ID|ID_Bus|ID_Line|DateHour_Start_Course|DateHour_End_Course|
On the other all payments made in these buses
dbo.Payments
|ID|ID_Bus|DateHour_Payment|
The goal is to add the notion of a Line in the payment table to get something like this
dbo.Payments
|ID|ID_Bus|DateHour_Payment|Line|
So I tried to do this :
/** I first added a Line column to the dbo.Payments table**/
UPDATE
Table_A
SET
Table_A.Line = Table_B.ID_Line
FROM
[dbo].[Payments] AS Table_A
INNER JOIN [dbo].[Courses_Bus] AS Table_B
ON Table_A.ID_Bus = Table_B.ID_Bus
AND Table_A.DateHour_Payment BETWEEN Table_B.DateHour_Start_Course AND Table_B.DateHour_End_Course
And this
UPDATE
Table_A
SET
Table_A.Line = Table_B.ID_Line
FROM
[dbo].[Payments] AS Table_A
INNER JOIN (
SELECT
P.*,
CP.ID_Line AS ID_Line
FROM
[dbo].[Payments] AS P
INNER JOIN [dbo].[Courses_Bus] CP ON CP.ID_Bus = P.ID_Bus
AND CP.DateHour_Start_Course <= P.Date
AND CP.DateHour_End_Course >= P.Date
) AS Table_B ON Table_A.ID_Bus = Table_B.ID_Bus
The main problem, apart from the fact that these requests do not seem to work properly, is that each table has several million lines that are increasing every day, and because of the datehour filter (mandatory since a single bus can be on several lines everyday) SSMS must compare each row of the second table to all rows of the other table.
So it takes an infinite amount of time, which will increase every day.
How can I make it work and optimise it ?
Assuming that this is the logic you want:
UPDATE p
SET p.Line = cb.ID_Line
FROM [dbo].[Payments] p JOIN
[dbo].[Courses_Bus] cb
ON p.ID_Bus = cb.ID_Bus AND
p.DateHour_Payment BETWEEN cb.DateHour_Start_Course AND cb.DateHour_End_Course;
To optimize this query, then you want an index on Courses_Bus(ID_Bus, DateHour_Start_Course, DateHour_End_Course).
There might be slightly more efficient ways to optimize the query, but your question doesn't have enough information -- is there always exactly one match, for instance?
Another big issue is that updating all the rows is quite expensive. You might find that it is better to do this in loops, one chunk at a time:
UPDATE TOP (10000) p
SET p.Line = cb.ID_Line
FROM [dbo].[Payments] p JOIN
[dbo].[Courses_Bus] cb
ON p.ID_Bus = cb.ID_Bus AND
p.DateHour_Payment BETWEEN cb.DateHour_Start_Course AND cb.DateHour_End_Course
WHERE p.Line IS NULL;
Once again, though, this structure depends on all the initial values being NULL and an exact match for all rows.
Thank you Gordon for your answer.
I have investigated and came with this query :
MERGE [dbo].[Payments] AS p
USING [dbo].[Courses_Bus] AS cb
ON p.ID_Bus= cb.ID_Bus AND
p.DateHour_Payment>= cb.DateHour_Start_Course AND
p.DateHour_Payment<= cb.DateHour_End_Course
WHEN MATCHED THEN
UPDATE SET p.Line = cb.ID_Ligne;
As it seems to be the most suitable in an MS-SQL environment.
It also came with the error :
The MERGE statement attempted to UPDATE or DELETE the same row more than once. This happens when a target row matches more than one source row. A MERGE statement cannot UPDATE/DELETE the same row of the target table multiple times. Refine the ON clause to ensure a target row matches at most one source row, or use the GROUP BY clause to group the source rows.
I understood this to mean that it finds several lines with identical
[p.ID_Bus= cb.ID_Bus AND
p.DateHour_Payment >= cb.DateHour_Start_Course AND
p.DateHour_Payment <= cb.DateHour_End_Course]
Yes, this is a possible case, however the ID is different each time.
For example, if two blue cards are beeped at the same time, or if there is a loss of network and the equipment has been updated, thus putting the beeps at the same time. These are different lines that must be treated separately, and you can obtain for example:
|ID|ID_Bus|DateHour_Payments|Line|
----------------------------------
|56|204|2021-01-01 10:00:00|15|
----------------------------------
|82|204|2021-01-01 10:00:00|15|
How can I improve this query so that it takes into account different payment IDs?
I can't figure out how to do this with the help I find online. Maybe this method is not the right one in this context.

SQL: IS NULL fails when trying to update values

I am currently trying to update some table values and I am stuck with a particular instance.
The situation is that I have a main table DBO.MAIN_INTERACTIONS that I join with an external table. Based on the below WHERE values I would then like to update the main database values. KCMACustomer.DBO.DATA_EXT_GREEN_ENR is a table that is linked to one particular product and my idea was to select and update the table rows of MAIN that do not have a connection with this GREEN_ENR table. That's why I put the EXT.NUMBER_OF_ACCOUNTS IS NULL.
So the rows I am trying to retrieve will have no match on this JOIN condition 'MAIN.GENID = EXT.GENID'. Is this what makes my update query fail? and would there be a better way to get the rows that have no connection with KCMACustomer.DBO.DATA_EXT_GREEN_ENR (the main table values are all the same, so I can't differentiate there)
Extra info: the second query does work, probably because there is a succesful 'MAIN.GENID = EXT.GENID' join
UPDATE
MAIN
SET
STATE_CODE='S8',
STATE_NAME='Reminder 1',
OLD_STATE='S4',
MODIFIED_DT = #NOW
OUTPUT INSERTED.ID, 0, 'AUTO-STATE','business','Doc.expected -> Reminder 1',INSERTED.CAMPAIGNID, #NOW,'S4','S8' INTO KCMACustomer.DBO.DATA_EBW_FFC_LOG_STATES
FROM KCMACUSTOMER.DBO.MAIN_INTERACTIONS AS MAIN
JOIN KCMACustomer.DBO.DATA_EXT_GREEN_ENR AS EXT
ON MAIN.GENID = EXT.GENID
WHERE
MAIN.STATE_CODE='S4'
AND
MAIN.TYPE_DEMAND='S4'
AND
EXT.NUMBER_OF_ACCOUNTS IS NULL
AND
DATEDIFF(hh, MAIN.MODIFIED_DT, #NOW)>=168
AND
MAIN.PRODUCT IN (#HELLO4YOU, #COMFORT_PACK, #PREMIUM_PACK)
In this case the 'MAIN.GENID = EXT.GENID' will have a match and it does update the records I want
UPDATE
MAIN
SET
STATE_CODE='S8',
STATE_NAME='Reminder 1 eID',
OLD_STATE='S4',
MODIFIED_DT = #NOW
OUTPUT INSERTED.ID, 0, 'AUTO-STATE','business','Doc expected -> Reminder 1 eID',INSERTED.CAMPAIGNID, #NOW,'S4','S8' INTO KCMACustomer.DBO.DATA_EBW_FFC_LOG_STATES
FROM KCMACUSTOMER.DBO.MAIN_INTERACTIONS AS MAIN
JOIN KCMACustomer.DBO.DATA_EXT_GREEN_ENR AS EXT
ON MAIN.GENID = EXT.GENID
WHERE
MAIN.STATE_CODE = 'S4'
AND
DATEDIFF(hh, MAIN.MODIFIED_DT, #NOW)>=120
AND
MAIN.PRODUCT IN (#HELLO4YOU, #COMFORT_PACK, #PREMIUM_PACK)
AND
EXT.NUMBER_OF_ACCOUNTS IS NOT NULL
AND
MAIN.DEMAND_DT > '2020-05-27 00:00:00'
JOIN implies an INNER JOIN
The use case you described requires a LEFT JOIN.
You will need to change your query so that it uses
LEFT JOIN KCMACustomer.DBO.DATA_EXT_GREEN_ENR AS EXT
ON MAIN.GENID = EXT.GENID
I also suggest to test the NULL condition of the same column you use in the join condition. So instead of doing
EXT.NUMBER_OF_ACCOUNTS IS NULL
check if
EXT.GENID IS NULL
You are more familiar with your data so it might not have an impact on your query. But the record from MAIN could be linked to a record in EXT, but that record could have NUMBER_OF_ACCOUNTS NULL.
However, checking on the GENID of the EXT table would ensure that a link was not found when trying to find a matching record in main.

UPDATE FUNCTION based on matching other column using SQL query in Access 2010

I have a table '1042sRegistration' I'm trying to update. It has a column 'IssueNumber' that I need to populate with values. Another table '1042sTransactions' has an 'IssueNumber' column as well that I want to pull the values from. These two tables also both have a column 'AccountNumber' that I'm trying to use as the condition to fill in 'IssueNumber' values. When I run the following query:
UPDATE 1042sRegistration
SET [1042sRegistration].IssueNumber = [1042sTransactions].IssueNumber
WHERE [1042sRegistration].AccountNumber = [1042sTransactions].AccountNumber;
0 rows are updated - even though I know they have thousands of matching 'AccountNumbers'
Try joining the two tables:
UPDATE 1042sRegistration INNER JOIN 1042sTransactions ON
1042sRegistration.AccountNumber = 1042sTransactions.AccountNumber
SET 1042sRegistration.IssueNumber = 1042sTransactions.IssueNumber
Perhaps your intention is:
UPDATE 1042sRegistration
SET [1042sRegistration].IssueNumber = (SELECT [1042sTransactions].IssueNumber
FROM [1042sTransactions]
WHERE [1042sRegistration].AccountNumber = [1042sTransactions].AccountNumber
);

SQL Update using value from join table

I tried using this sql to update a new column in a table from a value in table that already exists.
update "PROMOTION" t1
set "OFFER_CHAIN_ID" = poc."OFFER_CHAIN_ID"
from "PROMOTION_OFFER_CHAIN" poc
inner join "PROMOTION" on "PROMOTION"."ID" = poc."PROMOTION_ID"
What happened is that the first value of the join got replicated in all the subsequent entries. about a both tables. The original table has unique values all the values in the updated column are the same.
Eventually I used this SQL instead.
update "PROMOTION" t1
set "OFFER_CHAIN_ID" = poc."OFFER_CHAIN_ID"
from "PROMOTION_OFFER_CHAIN" poc
where
t1."ID" = poc."PROMOTION_ID"
This update works and duplicates all the data, 1000 unique elements in the original table, 1000 unique elements in the updated table.
Is this a bug, or is this the expected result?
SQL is behaving correctly. Your original query is:
update "PROMOTION" t1
--------^
set "OFFER_CHAIN_ID" = poc."OFFER_CHAIN_ID"
from "PROMOTION_OFFER_CHAIN" poc inner join
"PROMOTION"
-----------^
on "PROMOTION"."ID" = poc."PROMOTION_ID"
Note that the table PROMOTION is mentioned twice. Not good. So, the join takes place, producing lots of rows. Then there is no correlation to the t1 version of the table.
You don't mention the database you are using. In SQL Server, you would just do:
update p
set "OFFER_CHAIN_ID" = poc."OFFER_CHAIN_ID"
from "PROMOTION_OFFER_CHAIN" poc inner join
"PROMOTION" p
on p."ID" = poc."PROMOTION_ID";
Note the alias is used after the update (or table name with if there is no alias). Now the table is mentioned only once, so the update should behave as desired.