SQL Syntax Help - Update - sql

I have some code like this:
Update table_name
set
[column] = case when d.data is null, then null else d.columnname end.
from...
etc
My question is, how do I set up a function where the 'else d.columnname' is to sum up several columns from joins.
Would it be something like:
...then null else sum(d.column1 + rf.column2 + rwf.column3) as tempcolumn end,
or
...then null else (d.column1 + rf.column2 + rwf.column3) end,
What is the correct way to do a column sum in this set situation?

You can simply do:
update MyTable
set column =
case
when d.data is not null
then d.column1 + rf.column2 + rwf.column3
end
from ...
CASE will return NULL by default when there is no match.

Something like this should work:
UPDATE table_name
SET [column] = CASE WHEN d.data IS NULL
THEN null
ELSE (d.column1 + rf.column2 + rwf.column3)
END
FROM table_name
INNER JOIN other_table1 d ON ...
INNER JOIN other_table2 rf ON ...
INNER JOIN other_table3 rwf ON ...
Of course, in the query above you have to put in the correct relations between the tables in the INNER JOIN - ON clauses

Related

Case statement on a join in where clause

I am trying to use a CASE statement inside a WHERE clause for joining 2 tables. I want to evaluate POSITION_NBR2, if it is blank (null) then I want to join A.POSITION_NBR2 = B.POSITION_NBR Else I want to join A.POSITION_NBR = B.POSITION_NBR , however I am getting syntax errors while trying to run the following:
UPDATE #WORKTABLE
SET SLT_MEMBER = B.NAME
FROM PS_GHS_FTE_SLT A,
PS_EMPLOYEES B,
#WORKTABLE C
WHERE
CASE WHEN A.POSITION_NBR2 <> '' THEN A.POSITION_NBR2 = B.POSITION_NBR
ELSE A.POSITION_NBR = B.POSITION_NBR
END
AND A.DEPTID COLLATE Latin1_General_BIN = C.DEPTID COLLATE Latin1_General_BIN
AND B.EMPL_STATUS = 'A'
Use proper JOIN syntax and reasonable table aliases:
UPDATE WT
SET SLT_MEMBER = E.NAME
FROM PS_GHS_FTE_SLT GFS JOIN
PS_EMPLOYEES E
ON E.POSITION_NBR = (CASE WHEN GFS.POSITION_NBR2 <> '' THEN GFS.POSITION_NBR2 ELSE GFS.POSITION_NBR
END) JOIN
#WORKTABLE WT
ON GFS.DEPTID COLLATE Latin1_General_BIN = WT.DEPTID COLLATE Latin1_General_BIN
WHERE E.EMPL_STATUS = 'A';
I'm generally not a fan of using CASE for ON and WHERE clauses. In this case, though, it is only selectively choosing one column, so it doesn't bother me so much.

Case in update statement

I am trying to translate a talend code which has a nested IF statement into SQL
I thought I had translated it correctly, but no records are getting updated since the join condition fails. I added a top level case statement to check for existence of records, but wanted to double check from the experts here if my translation is correct at all.
Logic from Talend Mapper:
IF row32.DISPLAY_NAME_REPORTED IS NULL THEN
IF row31.REPORTED_DISPLAY_NAME IS NULL THEN
IF row87.SPEC_TYPE1 IS NULL THEN
IF row87.SPEC_TYPE2 IS null THEN
row34.Series
ELSE
row34.Series + row34.Type2
END
ELSE
row34.Series + row34.Type2
END
ELSE
row31.REPORTED_DISPLAY_NAME
END
ELSE
row32.DISPLAY_NAME_REPORTED
END
Corresponding case statement in SQL:
update a
set a.seriesbt = case when exists (select 1 from row32 x where
x.delivery_fk = a.delivery_fk) then
case when b.delivery_fk is not null and
b.DISPLAY_NAME_REPORTED is null then
case when c.reported_display_name is null then
case when d.SPEC_TYPE1 is null then
case when d.SPEC_TYPE2 is null then
a.series
else
a.series+a.SPEC_TYPE2 end
else a.series + a.SPEC_TYPE1 end
else c.reported_display_name end
else b.DISPLAY_NAME_REPORTED end
else a.series end
from tmpSales a
left join row32 b on b.delivery_fk = a.delivery_fk
left join row31 c on c.DELIVERY_FK = a.delivery_fk
left join row87 d on d.DELIVERY_FK = a.delivery_fk
Question is: Did I translate the talend mapper logic into SQL correctly? If not, can you please tell me what is wrong.
Should I be include "when exists" for each table?
I thought the left join should implicitly handle it.
You seem to have added an additional condition that was not in your original code. Coding the opposite way can make things simpler and avoid nested CASE expressions.
I changed your table alias to make it easier to understand where the columns come from without having to go back to the FROM clause.
UPDATE s
SET a.seriesbt = CASE WHEN r32.DISPLAY_NAME_REPORTED IS NOT NULL THEN r32.DISPLAY_NAME_REPORTED
WHEN r31.reported_display_name IS NOT NULL THEN r31.reported_display_name
WHEN r87.SPEC_TYPE1 IS NOT NULL THEN s.series /*row34.Series*/ + s.SPEC_TYPE1
WHEN r87.SPEC_TYPE2 IS NULL THEN s.series --row34.Series
ELSE s.series /*row34.Series*/ + s.SPEC_TYPE2
END
FROM tmpSales s
LEFT JOIN row32 r32 ON r32.delivery_fk = s.delivery_fk
LEFT JOIN row31 r31 ON r31.DELIVERY_FK = s.delivery_fk
LEFT JOIN row87 r87 ON r87.DELIVERY_FK = s.delivery_fk;
I just realized that it could be simplified even more.
UPDATE s
SET a.seriesbt = COALESCE( r32.DISPLAY_NAME_REPORTED,
r31.reported_display_name,
s.series /*row34.Series*/ + s.SPEC_TYPE1,
s.series /*row34.Series*/ + s.SPEC_TYPE2,
s.series --row34.Series
)
FROM tmpSales s
LEFT JOIN row32 r32 ON r32.delivery_fk = s.delivery_fk
LEFT JOIN row31 r31 ON r31.DELIVERY_FK = s.delivery_fk
LEFT JOIN row87 r87 ON r87.DELIVERY_FK = s.delivery_fk;

Condition if sql

I have this query
SELECT
SI_Num_Inventario = COALESCE (t.SI_Num_Inventario, c.SI_Num_Inventario),
SI_Ubicacion = COALESCE(t.SI_Ubicacion, c.SI_Ubicacion),
SI_Ubicacion_Fisica = COALESCE(t.SI_Ubicacion_Fisica, c.SI_Ubicacion_Fisica),
SI_Num_Articulo = COALESCE(t.SI_Articulo, c.SI_Num_Articulo),
NULL,
SI_Num_Conteo = COALESCE(cs.SI_Num_Conteo,2),
GETDATE(),
'Admin',
c.SI_OV
FROM
SI_Inventario_Teorico_QAD t
FULL JOIN
SI_Conteo c ON t.SI_Articulo = c.SI_Num_Articulo
AND t.SI_Ubicacion = c.SI_Ubicacion
INNER JOIN
SI_Maestro_Ref_QAD m ON t.SI_Articulo = m.SI_Num_Articulo
OR c.SI_Num_Articulo = m.SI_Num_Articulo
FULL JOIN
SI_Consecutivo cs ON c.SI_Num_Inventario = cs.SI_Num_Inventario
AND cs.SI_Estado = 0
WHERE
c.SI_Num_Articulo = 201423 OR t.SI_Articulo = 201423
And I'm trying to tell you that if c.SI_OV IS NULL INSERT THIS `INSERT INTO``
IF c.SI_OV IS NULL
INSERT INTO SI_Conteo(SI_Num_Inventario, SI_Ubicacion,SI_Num_Articulo, SI_Cantidad,SI_Num_Conteo,SI_Fecha_Conteo, SI_Usuario,SI_OV)
And if it is not NULL insert me this other
ELSE
INSERT INTO SI_Conteo(SI_Num_Inventario, SI_Ubicacion_Fisica, SI_Num_Articulo, SI_Cantidad,SI_Num_Conteo,SI_Fecha_Conteo, SI_Usuario,SI_OV)
END IF;
In short: the CASE construct needs to "live" in your SELECT clause of you SQL statement. The receiving INSERT clause should always mention both column names like this
INSERT INTO SI_CONTEO (SI_Num_Inventario,
SI_Ubicacion, SI_Ubicacion_fisico,
SI_Num_Articulo, SI_Cantidad,SI_Num_Conteo,
SI_Fecha_Conteo, SI_Usuario,SI_OV)
SELECT SI_Num_Inventario = COALESCE (t.SI_Num_Inventario,c.SI_Num_Inventario),
SI_Ubicacion = CASE WHEN SI_OV IS NULL THEN COALESCE(t.SI_Ubicacion, c.SI_Ubicacion) END,
SI_Ubicacion_Fisica = CASE WHEN NOT SU_OV IS NULL THEN COALESCE(t.SI_Ubicacion_Fisica, c.SI_Ubicacion_Fisica) END,
SI_Num_Articulo = COALESCE(t.SI_Articulo, c.SI_Num_Articulo),
NULL, ...
if else in non query language ~= CASE WHEN cond1 ELSE cond2 END in SQL
Use the below query:
INSERT INTO SI_Conteo(SI_Num_Inventario,SI_Ubicacion,SI_Ubicacion_Fisica,SI_Num_Articulo, SI_Cantidad,SI_Num_Conteo,SI_Fecha_Conteo,
SI_Usuario,SI_OV)
SELECT
SI_Num_Inventario = COALESCE (t.SI_Num_Inventario,c.SI_Num_Inventario),
(CASE WHEN c.SI_OV IS NULL THEN COALESCE(t.SI_Ubicacion, c.SI_Ubicacion) ELSE NULL END)AS SI_Ubicacion,
(CASE WHEN c.SI_OV IS NOT NULL THEN COALESCE(t.SI_Ubicacion_Fisica, c.SI_Ubicacion_Fisica) ELSE NULL END)AS SI_Ubicacion_Fisica,
SI_Num_Articulo = COALESCE(t.SI_Articulo, c.SI_Num_Articulo),
NULL,
SI_Num_Conteo = COALESCE(cs.SI_Num_Conteo,2),
GETDATE(),
'Admin',
c.SI_OV
FROM SI_Inventario_Teorico_QAD t
full JOIN SI_Conteo c
ON t.SI_Articulo = c.SI_Num_Articulo
AND t.SI_Ubicacion = c.SI_Ubicacion
INNER JOIN SI_Maestro_Ref_QAD m
ON t.SI_Articulo = m.SI_Num_Articulo
OR c.SI_Num_Articulo = m.SI_Num_Articulo
FULL JOIN SI_Consecutivo cs
ON c.SI_Num_Inventario = cs.SI_Num_Inventario
AND cs.SI_Estado = 0
WHERE c.SI_Num_Articulo = 201423 OR t.SI_Articulo = 201423
Basicallly I have combined both inserts into one Insert, which includes both of the columns , where you want a switch based on Case. Only one column out of SI_Ubicacion and SI_Ubicacion_Fisica will be set based on s.SI_OV value. Hope you got what I am saying,.
Note: I Could not execute this as I don't have any table structure/data with me. I have modified your query manually and posted it here.
Clarify your question. You have a select statement that returns a resultset of some number of rows. You propose to insert them into a table. You claim to need to use if/else (or similar) but it is not clear why. Your proposed insert statements differ by a single column - is that correct? If so, then you probably need to use 2 different insert statements - one to handle the non-null situation and one to handle the null situation. You cannot dynamically change the column list of the inserted table.
OTOH, perhaps you just want to swap the value inserted into the SI_Ubicacion column of the SI_Conteo table? If so, you can probably use isnull or coalesce in the select statement (much like you do now - just differently).

My query doesn't get the right value

My query doesn't give the right output.
I tried with different way such as with CTE as well but nothing help.
I'm trying to write View to display available products with quantity but as some data is not available in StockCloseInventory table it displaying me 0 even though records are available for some products.
Here is my query:
SELECT TOP (100) PERCENT
SOI.InStockPrdID
, SOI.ProdName
, SOI.TradeDrugId
, ISNULL(SOI.Quantity, 0) AS INQTY
, ISNULL(SCI.QuantitySold, 0) AS OUTQTY
, ISNULL(SOI.Quantity, 0) - ISNULL(SCI.QuantitySold, 0) AS AQTY
, SOI.UnitPrice
FROM dbo.StockInventory AS SOI
LEFT OUTER JOIN dbo.StockCloseInventory AS SCI
ON SOI.InStockPrdID = SCI.InStockPrdID
AND SOI.SoldOut <> 1
LEFT OUTER JOIN dbo.vwTradeDrug AS VTD
ON SOI.TradeDrugId = VTD.TradeDrugId
ORDER BY SOI.ProdName
And this is the output of my View:
And here is my Tables
Table: StockInventory
Table: StockCloseInventory
vwTradeDrug view:
CREATE VIEW [dbo].[vwTradeDrug]
AS
SELECT
T.TradeDrugId
, T.GenericDrugId
, T.TradeName
, G.GenericProprietaryName
, G.DosageType
, G.Strength
, T.TradeName + ',' + G.GenericProprietaryName + ',' + G.DosageType
+ ',' + G.Strength AS TradeFullName
FROM dbo.TradeDrug AS T
INNER JOIN Inventory.GenericDrug AS G
ON T.GenericDrugId = G.GenericId
GO
The problem is with SOI.SoldOut <> 1
First, as Pouya Kamyar pointed out, it is more conventional to include this in a WHERE clause than in a JOIN.
However, the issue is that the value of this field is mostly NULL.
What you want is something more like this:
WHERE SOI.SoldOut IS NULL
OR SOI.SoldOut <> 1
I Suggest bring "AND SOI.SoldOut <> 1" in WHERE clause not in join terms
Either change the null data in sold out to be 0 or 1 OR...
handle the nulls so that the boolean compare results in a true or false instead of "NULL" as below.
SELECT TOP (100) PERCENT
SOI.InStockPrdID
, SOI.ProdName
, SOI.TradeDrugId
, ISNULL(SOI.Quantity, 0) AS INQTY
, ISNULL(SCI.QuantitySold, 0) AS OUTQTY
, ISNULL(SOI.Quantity, 0) - ISNULL(SCI.QuantitySold, 0) AS AQTY
, SOI.UnitPrice
FROM dbo.StockInventory AS SOI
LEFT OUTER JOIN dbo.StockCloseInventory AS SCI
ON SOI.InStockPrdID = SCI.InStockPrdID
AND ISNULL(SOI.SoldOut,0) <> 1 -- this should do the trick
LEFT OUTER JOIN dbo.vwTradeDrug AS VTD
ON SOI.TradeDrugId = VTD.TradeDrugId
ORDER BY SOI.ProdName
Remember Boolean compares on Null values result in NULL (a third value in a Boolean compare!) so SOI.SoldOut <> 1 when SOI.SoldOut is null will result in NULL instead of a true/false you're expecting.

Trouble with case statement

I am having problems with this case statement. I don't know what I am doing wrong but I get the error:
Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.
I have a case when the field equals a value then do a left outer join but if the field equals a different value then do a inner join.
This is my query:
SELECT
case
when oqt = '26' then
(Select qm.id_oqm, cast(isNull(id_eval, '') as varChar(50)) + ' - ' + qm.methodName as methodName, qm.methodName as actualMethod,cv.*
FROM OQMethods QM left outer join courseversions cv on cv.evalid = QM.id_eval and cv.courselanguage = 'EN' and cv.courseactive='Y' and cv.id_cp > 0
WHERE QM.id_oqt in (SELECT tempoq.oqt FROM tempoq INNER JOIN OQMethods ON tempoq.oqt = OQMethods.id_oqt)and active = 1)
END,
case
when oqt = '31' then
(Select qm.id_oqm, cast(isNull(id_eval, '') as varChar(50)) + ' - ' + qm.methodName as methodName, qm.methodName as actualMethod,cv.*
FROM OQMethods QM inner join courseversions cv on cv.evalid = QM.id_eval and cv.courselanguage = 'EN' and cv.courseactive='Y' and cv.id_cp > 0
where QM.id_oqt in (SELECT tempoq.oqt FROM tempoq INNER JOIN OQMethods ON tempoq.oqt = OQMethods.id_oqt) and active = 1)
END
from tempoq
The case is an expression that must evaluate to a value. The Select statements that you have return multiple values.
It would seem that you're trying to use Case like it's a C# switch? If that's the case, then you're likely better off with an IF ELSE IF construction.
It looks like you want to do something like this rather than using a CASE statement.
DECLARE #t int
-- This would contain your oqt value
SET #t =1
IF #t = 1
BEGIN
SELECT * FROM tableA
END
ELSE IF #t = 2
BEGIN
SELECT * FROM TableB
END
Select qm.id_oqm, cast(isNull(id_eval, '') as varChar(50)) + ' - ' + qm.methodName as methodName, qm.methodName as actualMethod,cv.*
FROM OQMethods QM
inner join tempoq on tempoq.oqt = QM.id_oqt
left outer join courseversions cv on cv.evalid = QM.id_eval and cv.courselanguage = 'EN' and cv.courseactive='Y' and cv.id_cp > 0
WHERE active = 1 and (tempoq.oqt = '26' or (tempoq.oqt = '31' and courseversions.* is not null))
left outer join means join OQMethods's data which even no match data from courseversions,
then filter the data with null courseversions.* that is inner join.
Hope I have the right understanding.