SELECT within UPDATE CASE statement - sql-server

New to t-sql, trying to get the following Select statement to work. Any ideas?
Cheers,
Julian
UPDATE DRPDATA
SET DRPDATA.LocatieCode = CASE
WHEN SUBSTRING([Org eenheid code],1,2) IN ('91','92','93') THEN 'BZ'
ELSE (SELECT Huizen.IDHuis FROM DRPDATA INNER JOIN Huizen ON DRPDATA.Locatie = Huizen.NrHuis)
END

I would use two queries. If you need them to be atomic, use a transaction. You're adding a lot of complexity here for no real reason. Running as a single statement is likely more complicated for the DB engine, too, so two statements may perform better.
UPDATE DRPDATA
SET DRPDATA.LocatieCode = 'BZ'
WHERE SUBSTRING([Org eenheid code],1,2) IN ('91','92','93');
UPDATE DRPDATA
SET DRPDATA.LocatieCode = Huizen.IDHuis
FROM DRPDATA
INNER JOIN Huizen
ON DRPDATA.Locatie = Huizen.NrHuis
WHERE SUBSTRING([Org eenheid code],1,2) NOT IN ('91','92','93');
Note that the WHERE clauses make the two queries mutually exclusive, so the order you run them will not matter.

Looks like the problem is the subquery isn't correlated and is probably returning more than the one value allowed.
You can move the join like this
update d
set locatiecode = case when .... end
from drpdata d
join huizen h on ...

Check Below Query
UPDATE DRPDATA
SET LocatieCode =
CASE
WHEN SUBSTRING(a.[Org eenheid code],1,2) IN ('91','92','93') THEN 'BZ'
ELSE b.IDHuis END
FROM DRPDATA a INNER JOIN Huizen b ON a.Locatie = b.NrHuis

Related

Executing part of stored procedure based on condition

I am trying to load to a table based on load types - Full or Incremental that is being passed as parameter in stored procedure. I was able to try with substitution variable with one line of code previously, but the below code doesn't seem to work -
Stored procedure possible arguments:
LOAD_TYPE=FULL
LOAD_TYPE=INCR
var incr_condition = (load_type=='INCR')?"INNER JOIN temp_table"
with temp_table(
select data
from table a
where dt between 01-01-2019 and 09-09-2020
)
select *
from table b
${incr_condition} -- execute only if load_type=INCR
INNER JOIN TABLE C ON B.ID = C.ID
Is there any way to restrict the with clause to execute only if the load_type==INCR? Please advice.
I think the conditional operator (question mark) must have a false part in addition to the true part. Otherwise, it generates a syntax error when there's a semicolon ending the line. This example obviously doesn't run anything, but it will return the values assigned to the "out" variable, which would be run.
Since you're using a replacement variable ${incr_condition} be sure to use backticks to open and close your SQL string.
create or replace procedure foo(LOAD_TYP string)
returns string
language javascript
as
$$
var load_type = LOAD_TYP;
var incr_condition = (load_type === 'INCR') ? "INNER JOIN temp_table" : "";
var out = `
with temp_table(
select data
from table a
where dt between 01-01-2019 and 09-09-2020
)
select *
from table b
${incr_condition} -- execute only if load_type=INCR
INNER JOIN TABLE C ON B.ID = C.ID
`;
return out;
$$;
call foo('INCR'); --Adds the inner join
call foo('FULL'); --Does not add the inner join
I also recommend changing your comparison on strings from == to ===. For details on why, reference What is the correct way to check for string equality in JavaScript?.

Does SQL Server CASE expression not do short circuit?

Appropriate if somebody could help us to optimize below query
As per execution plane it seems the else part sub query is always executing, irrespective of conditions.
Won't CASE be short circuited? Why is it executing, even though it is not necessary?
IF OBJECT_ID('#Calculation') IS NOT NULL
DROP TABLE #Calculation;
SELECT
Result.IdDeckungsbeitrag,
Result.wert AS Wert,
REPLACE(#Formula, '<#PackagingCosts> ', Result.wert) AS Kalkulation
INTO
#Calculation
FROM
(SELECT
deck.IdDeckungsbeitrag,
CASE
WHEN lp.ID_VERPACKUNG_2 IS NULL
AND lp.ID_VERPACKUNG_3 IS NULL
THEN vg.VERPACKUNGSKOSTEN_PRO_EINHEIT * deck.Menge
ELSE
(
SELECT SUM(temp.me) * vg.VERPACKUNGSKOSTEN_PRO_EINHEIT
FROM
(
SELECT SUM(gv.MENGE) AS me
FROM dbo.KUNDENRECHNUNG_POSITION krp
LEFT JOIN dbo.LIEFERSCHEIN_POSITION lp
ON lp.ID_LIEFERSCHEIN_POSITION = krp.ID_LIEFERSCHEIN_POSITION
LEFT JOIN dbo.GEBINDE_VERLADEN gv
ON gv.ID_LIEFERSCHEIN_POSITION = lp.ID_LIEFERSCHEIN_POSITION
LEFT JOIN dbo.MATERIAL_BESTAND mb
ON mb.ID_MATERIAL_BESTAND = gv.ID_MATERIAL_BESTAND
LEFT JOIN dbo.MATERIAL_GEBINDE mg
ON mg.ID_MATERIAL_BESTAND = mg.ID_MATERIAL_BESTAND
WHERE mg.CHARGE_NUMMER = deck.Charge
GROUP BY mg.ID_VERPACKUNG
) temp
)
END AS wert
FROM #DeckungsbeitragCalculationPositions_TVP deck
LEFT JOIN dbo.KUNDENRECHNUNG_POSITION krp
ON krp.ID_KUNDENRECHNUNG_POSITION = deck.IdDeckungsbeitrag
LEFT JOIN dbo.LIEFERSCHEIN_POSITION lp
ON lp.ID_LIEFERSCHEIN_POSITION = krp.ID_LIEFERSCHEIN_POSITION
LEFT JOIN dbo.VERPACKUNG vg
ON vg.ID_VERPACKUNG = lp.ID_VERPACKUNG_1
WHERE deck.IdMandant = #Id_Mandant
) Result;
Don't think of it as short-circuit or not. That's a procedural code mindset rather than a set-based mindset.
In SQL, the actual "execution" happens in the realm of table or index scans and seeks, hash matches, sorts, and the like. Pull data from different tables into a working set that will eventually produce the desired relational result.
Not seeing any real or projected execution plan, in this case (no pun intended), I suspect the query optimizer decided it was most efficient to first produce this result set in memory:
SELECT mg.ID_VERPACKUNG, mg.CHARGE_NUMMER, SUM(gv.MENGE) AS me
FROM dbo.KUNDENRECHNUNG_POSITION krp
LEFT JOIN dbo.LIEFERSCHEIN_POSITION lp
ON lp.ID_LIEFERSCHEIN_POSITION = krp.ID_LIEFERSCHEIN_POSITION
LEFT JOIN dbo.GEBINDE_VERLADEN gv
ON gv.ID_LIEFERSCHEIN_POSITION = lp.ID_LIEFERSCHEIN_POSITION
LEFT JOIN dbo.MATERIAL_BESTAND mb
ON mb.ID_MATERIAL_BESTAND = gv.ID_MATERIAL_BESTAND
LEFT JOIN dbo.MATERIAL_GEBINDE mg
ON mg.ID_MATERIAL_BESTAND = mg.ID_MATERIAL_BESTAND
GROUP BY mg.ID_VERPACKUNG, mg.CHARGE_NUMMER
This is the subquery from the ELSE clause, minus the WHERE clause conditions and with additional info added to the SELECT to make the match more effective. If the query optimizer can't be confident of meeting the WHEN clause a high percentage of the time, it might believe producing this larger ELSE set once to match against as needed is more efficient. Put another way, if it thinks it will have to run that subquery a lot anyway, it may try to pre-load it for all possible data.
We don't know enough about your database to suggest real solutions, but indexing around the ID_VERPACKUNG_2, ID_VERPACKUNG_3, and CHARGE_NUMMER fields might help. You might also be able to use a CTE, temp table, or table variable to help Sql Server to a better job of caching this data just once.
If the conditions of where are not met then the else will become active. If this is always the case then you would expect the following to return no rows:
select *
FROM #DeckungsbeitragCalculationPositions_TVP deck
LEFT JOIN dbo.KUNDENRECHNUNG_POSITION krp ON krp.ID_KUNDENRECHNUNG_POSITION = deck.IdDeckungsbeitrag
LEFT JOIN dbo.LIEFERSCHEIN_POSITION lp ON lp.ID_LIEFERSCHEIN_POSITION = krp.ID_LIEFERSCHEIN_POSITION
WHERE lp.ID_VERPACKUNG_2 IS NULL
AND lp.ID_VERPACKUNG_3 IS NULL

multiple part identifier couldn't be bound

i am trying to make a query that finds the item number and change the shelf number based on the id in another table but i getting a
multiple part identifier couldn't be bound
on SET and WHERE how do i fix that or are there another way around this
use [ISTABLocalDB]
SELECT
ps.[ShelfNumber], P.[ItemNumber]
FROM
[file].[Item] P
inner join [file].[ItemPart] PS on P.[ID] = PS.[ID]
UPDATE [file].[ItemPart]
SET ps.[ShelfNumber]='Test'
WHERE P.[ItemNumber] LIKE 'N84754'
UPDATE PS
SET [ShelfNumber] = 'Test'
FROM [file].[ItemPart] PS
JOIN [file].[Item] P ON P.[id] = PS.[id]
WHERE P.[ItemNumber] = 'N84754'

Writing the SQL CASE statement to update a column based on the value of another column from another table

I need to update the values in a Column named "TravelAgencyID2" in "dbo.ReservationStay" based on the values of column "TravelAgencyTypeCode" of "dbo.TravelAgency".
The condition of the update is like this: If TravelAgencyTypeCode in dbo.TravelAgency is NOT EQUAL to 'DMC', then TravelAgencyID2 = TravelAgencyID (from dbo.ReservationStay), ELSE TravelAgencyID2 remains unchanged.
SO, you only need to update those rows WHERE a condition is met?
UPDATE rs
SET rs.TravelAgencyID2 = rs.TravelAgencyID
FROM ReservationStay rs
INNER JOIN TravelAgency ta on rs.TravelAgencyID2 = ta.ID
WHERE ta.TravelAgencyTypeCode != 'DMC'
This will only update the rows you need, without touching anything else.

Update field from another table

Is there a better way to write the following simple SQL Server 2005 update statement? This just seems a bit messy inefficient.
UPDATE QuotationItem
SET Recurring_Cost =
(SELECT TOP (1) Recurring_Cost
FROM Products
WHERE (Remote_ID = QuotationItem.Product_ID))
WHERE (Quotation_ID = 115)
Thanks,
Nick
How About using a join
UPDATE QuotationItem
SET Recurring_Cost = p.recurring_cost
FROM QuotationItem q join Products p on q.Product_ID = p.Remote_ID
WHERE q.Quotation_ID = 115
Is your TOP 1 really needed? If it is, since you don't specify an ordering, you've got pretty random results from your query anyway! If it is not really necessary, this will do:
UPDATE q
SET Recurring_Cost = p.RecurringCost
FROM QuotationItem q
INNER JOIN
Products p
ON p.Remote_ID = q.Product_ID
WHERE q.Quotation_ID = 115

Resources