Condition if sql - 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).

Related

SQL Query merge

I am working on a scenario where for example I need to search customers by telephone and/or email address.
for example
if :lv_telephone <> '' then
lt_phone = select a.customer from customer_master a inner join telephone as b on a.address = b.address;
end if;
if :lv_email <> '' then
lt_email = select a.customer from customer_master a inner join email as b on a.address = b.address;
end if;
DB - HANA.
I want to create one final result merging both email and phone table only if they both have result set. Any pointers on how to do it?
You may avoid any script logic and "merge" your results in a plain SQL with conditions on variables (regardless of their source):
select a.customer
from customer_master a
left join telephone t
on a.address = t.address
and lv_telephone != ''
left join email e
on a.address = e.address
and lv_email != ''
where 1 = 1
/*Applies only when lv_telephone is not ''*/
and map(lv_telephone, '', '', t.address) is not null
/*Applies only when lv_email is not ''*/
and map(lv_email, '', '', e.address) is not null
This may also be adapted if you need to filter by passed values: compare with variable value instead of null. If variables come from SQLScript code, this can be embedded into SQLScript code. If they come from outside (e.g. some external language communicating with your DB), you may use bind variables and plain SQL withour additional script wrapper.
Below is example with standard SAP tables:
create procedure test_sp ( in iv_tel nvarchar(10), in iv_email nvarchar(10))
as
begin
select b.*
from sapdbh.t006 as b
left join sapdbh.t006a as t
on b.msehi = t.msehi
and t.spras = 'R'
and :iv_tel != ''
left join sapdbh.t006t as e
on b.dimid = e.dimid
and e.spras = 'R'
and :iv_email != ''
where 1 = 1
and case
when :iv_tel != ''
then t.msehi
else ''
end is not null
and case
when :iv_email != ''
then e.dimid
else ''
end is not null
;
end;
And execution plans below (I didn't use mandt in join so you may observe results are multiplied when join is introduced):
With call test_sp('', ''); one table accessed.
With call test_sp('X', ''); two tables accessed.
With call test_sp('X', 'X'); three tables accessed.

How to check sql database table field null or 0 and if so replace it with other column

I have a SQL query; I want to check two columns in query to check if they are null or 0; if so, then I want to replace then with other column's values.
Here is my query: I have used coalesce to check if it is null but how can I check for 0 and also how can I replace the columns with other values?
SELECT
t.Name
,t.Code
,c.Description
,st.APriceOld
,st.CPriceOld
,st.APriceNew
,st.CPriceNew
COALESCE(st.APriceOld,st.APriceNew),
COALESCE(st.CPriceOld,st.CPriceNew)
FROM
Table t
INNER JOIN
STCP st ON st.PriceId = t.PriceId
Can anybody help me to get the expected result?
So if old price values are 0 or null, then they should be replaced with new price values
One more approach - use nullif() function:
SELECT
t.Name
,t.Code
,c.Description
,st.APriceOld
,st.CPriceOld
,st.APriceNew
,st.CPriceNew
COALESCE(NULLIF(st.APriceOld, 0), st.APriceNew),
COALESCE(NULLIF(st.CPriceOld, 0), st.CPriceNew)
FROM
Table t
INNER JOIN
STCP st ON st.PriceId = t.PriceId
You could try:
SELECT
t.Name,
t.Code,
c.Description,
st.APriceOld,
st.CPriceOld,
st.APriceNew,
st.CPriceNew,
CASE WHEN COALESCE(st.APriceOld, 0) <> 0
THEN st.APriceOld ELSE st.APriceNew END AS APrice,
CASE WHEN COALESCE(st.CPriceOld, 0) <> 0
THEN st.CPriceOld ELSE st.CPriceNew END AS CPrice
FROM Table t
INNER JOIN STCP st ON st.PriceId = t.PriceId;
The logic here is to use COALESCE to first conditionally replace a NULL old price value with zero. Then, we use a CASE expression to replace zero values (either naturally being zero, or having been coaleseced to zero) with the backup value.

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;

Looking for a way to not show duped rows using a SQL query

SELECT
AEC.gwd_people.id_people,
AEC.gwd_people.uid_people,
AEC.gwd_people.cod_people,
AEC.gwd_people.name_people,
AEC.gwd_people.surname_people,
AEC.gwd_people.email,
AEC.gwd_people.people_status,
AEC.gwd_people.people_type,
AEC.gwd_people.facility_reference,
AEC.gwd_people.sc_id_sap,
AEC.gwd_people.c_id_sap,
AEC.gwd_people.descr_people,
AEC.gwd_people.cod_sector,
AEC.gwd_people.descr_sector,
AEC.gwd_people.cod_org_sector,
AEC.gwd_people.descr_org_sector,
AEC.gwd_people.cod_company,
AEC.gwd_people.descr_company,
AEC.gwd_people.cod_company_sap,
AEC.gwd_people.cod_department,
AEC.gwd_department.descr_department,
AEC.gwd_people.cod_subdepartment,
AEC.gwd_people.descr_subdepartment,
AEC.gwd_people.cod_cdc,
AEC.gwd_cost_center.descr_cdc,
AEC.gwd_people.cod_category_job,
AEC.gwd_people.descr_category_job,
AEC.gwd_people.cod_people_job,
AEC.gwd_people.descr_people_job,
AEC.gwd_people.cod_position,
AEC.gwd_people.descr_position,
AEC.gwd_people.uohr,
AEC.gwd_people.qual_contract,
AEC.gwd_people.level_position,
AEC.gwd_people.cod_manager,
AEC.gwd_people.cod_validator,
AEC.gwd_people.cod_country,
AEC.gwd_people.descr_country,
AEC.gwd_people.cod_region_area,
AEC.gwd_people.descr_region_area,
AEC.gwd_people.descr_city,
AEC.gwd_people.descr_site,
AEC.gwd_people.address_1,
AEC.gwd_people.address_2,
AEC.gwd_people.descr_building,
AEC.gwd_people.descr_room,
AEC.gwd_people.validity_date,
AEC.aec_workstation.cod_workstation,
AEC.aec_workstation.geometry,
AEC.aec_workstation.drawing,
AEC.gwd_people.tax_code,
AEC.gwd_people.phone_1,
AEC.gwd_people.phone_2,
AEC.gwd_people.phone_3,
AEC.gwd_people.phone_4,
AEC.gwd_people.ext_email_1,
AEC.gwd_people.flagvip,
AEC.gwd_people.hiring_date,
AEC.gwd_people.cease_date,
AEC.gwd_people.cid_resp_liv_1,
AEC.gwd_people.cid_resp_liv_2,
AEC.gwd_people.id_resp,
AEC.gwd_people.descr_resp,
AEC.gwd_people.id_ref,
AEC.gwd_people.descr_ref,
AEC.gwd_people.descr_ext_people,
AEC.gwd_people.ext_email_2,
AEC.gwd_people.descr_sede,
(CASE WHEN AEC.aec_r_workstation_people.cod_people IS NULL
THEN AEC.gwd_people.idplan
ELSE NULL
END) AS idplan,
(CASE WHEN AEC.aec_r_workstation_people.cod_people IS NOT NULL
THEN SUBSTRING(AEC.aec_workstation.cod_workstation, 5, 7)
ELSE NULL
END) AS idplan_wrkst,
(CASE WHEN AEC.aec_r_workstation_people.cod_people IS NULL
THEN AEC.view_iam_r_unitp_building.IDEDIFICIO
ELSE NULL
END) AS cod_building,
(CASE WHEN AEC.aec_r_workstation_people.cod_people IS NOT NULL
THEN SUBSTRING(AEC.aec_workstation.cod_workstation, 5, 3)
ELSE NULL
END) AS cod_building_wrkst,
(CASE WHEN AEC.aec_r_workstation_people.cod_people IS NOT NULL
THEN AEC.aec_workstation.id_room
ELSE NULL
END) AS id_room_wrkst,
(CASE WHEN AEC.aec_r_workstation_people.cod_people IS NOT NULL
THEN AEC.aec_workstation.id_room
ELSE NULL
END) AS id_room_wrkst2
FROM AEC.gwd_people
LEFT OUTER JOIN AEC.view_iam_r_unitp_building ON
AEC.view_iam_r_unitp_building.IDUNITPROD = AEC.gwd_people.cod_sector
LEFT OUTER JOIN AEC.aec_r_workstation_people ON AEC.gwd_people.cod_people =
AEC.aec_r_workstation_people.cod_people
LEFT OUTER JOIN AEC.aec_workstation ON AEC.aec_workstation.cod_workstation
= AEC.aec_r_workstation_people.cod_workstation
LEFT OUTER JOIN AEC.gwd_department ON AEC.gwd_department.cod_department =
AEC.gwd_people.cod_department
LEFT OUTER JOIN AEC.gwd_cost_center ON AEC.gwd_cost_center.cod_cost_center
= AEC.gwd_people.cod_cdc
This is my query and I'm using SQL Server 13, it returns 6752 rows, 44 of them are duped. I've tried everything I know to avoid showing those duped entries but I'm out of ideas, so I'm looking for some helpful tips :-) One of the biggest problem is taht all fields are necessary, so I can't get rid of "AEC.aec_workstation.geometry" that causes problems with SELECT DISTINCT.
Find a PK value from your first table that's returning a duplicate row and start with the following query:
SELECT
COUNT(1)
FROM
AEC.gwd_people
WHERE
AEC.gwd_people.PrimaryKeyColumn = 'SomeValue'
Now start adding joins one by one, checking the result of the COUNT(1) each time:
SELECT
COUNT(1)
FROM
AEC.gwd_people
LEFT OUTER JOIN AEC.view_iam_r_unitp_building ON AEC.view_iam_r_unitp_building.IDUNITPROD = AEC.gwd_people.cod_sector
WHERE
AEC.gwd_people.PrimaryKeyColumn = 'SomeValue'
And then...
SELECT
COUNT(1)
FROM
AEC.gwd_people
LEFT OUTER JOIN AEC.view_iam_r_unitp_building ON AEC.view_iam_r_unitp_building.IDUNITPROD = AEC.gwd_people.cod_sector
LEFT OUTER JOIN AEC.aec_r_workstation_people ON AEC.gwd_people.cod_people = AEC.aec_r_workstation_people.cod_people
WHERE
AEC.gwd_people.PrimaryKeyColumn = 'SomeValue'
Until you see the amount of rows jump up when you don't expect it to. You are most likely:
Not considering that duplicate rows can be expected.
Missing another join column on a table.
Having duplicate rows on a table.
... or combination of these.
Your table design makes it a bit hard to understand their relations. This is what it looks like to me:
gwd_department {1:n} gwd_people
gwd_people {m:n} aec_workstation
gwd_people {m:n} view_iam_r_unitp_building
gwd_people {?:n} gwd_cost_center
So for a person linked to 3 aec_workstations and 4 view_iam_r_unitp_buildings, you'd produce 3 x 4 = 12 result rows. Is there no further relation between an aec_workstation and a view_iam_r_unitp_building? If not, then why do you combine them in your query?
I don't know whether cod_cdc is supposed to be short for cod_cost_center or something different. If this is an m:n relation, too, you are doing the same thing again with gwd_cost_center related to aec_workstation and view_iam_r_unitp_building.
Having said this: Either add the missing criteria or ask yourself what you want to select after all.

Is it possible to insert an IF clause inside of a WHERE clause in a SELECT?

sorry if this is a dumb question, I'm new to PL/SQL.
I have a PL/SQL Stored Procedure which retrieves data from a table.
There are 2 optional parameters which can be null. If they're not null they should be part of the WHERE clause.
This is the SELECT:
SELECT DISTINCT PN.PART_NUMBER, PN.SHORT_CODE, DES.DESCRIPTION
FROM MAS_PART PN
LEFT JOIN CF_DESCRIPTION DES
ON PN.LOCAL_DESCRIPTION_ID = DES.DESCRIPTION_ID
WHERE PN.PART_CODE = 'M'
AND PN.PART_TYPE_ID = IN_PART_TYPE_ID
AND PN.PART_GROUP_ID = IN_PART_GROUP_ID
ORDER BY PN.PART_NUMBER;
The two variables are IN_PART_TYPE_ID and IN_PART_GROUP_ID. Is there any way to evaluate the WHERE clauses regarding these two variables only when they're NOT NULL? Or the only way is to repeat the SELECT 3 times using IF clauses and changing the WHERE clauses?
OR operatior will help:
SELECT DISTINCT PN.PART_NUMBER, PN.SHORT_CODE, DES.DESCRIPTION
FROM MAS_PART PN
LEFT JOIN CF_DESCRIPTION DES
ON PN.LOCAL_DESCRIPTION_ID = DES.DESCRIPTION_ID
WHERE PN.PART_CODE = 'M'
AND (PN.PART_TYPE_ID = IN_PART_TYPE_ID or IN_PART_TYPE_ID is null)
AND (PN.PART_GROUP_ID = IN_PART_GROUP_ID or IN_PART_GROUP_ID is null)
ORDER BY PN.PART_NUMBER;
Another option is to use NVL:
SELECT DISTINCT PN.PART_NUMBER, PN.SHORT_CODE, DES.DESCRIPTION
FROM MAS_PART PN
LEFT JOIN CF_DESCRIPTION DES
ON PN.LOCAL_DESCRIPTION_ID = DES.DESCRIPTION_ID
WHERE PN.PART_CODE = 'M'
AND PN.PART_TYPE_ID = NVL(IN_PART_TYPE_ID, PN.PART_TYPE_ID)
AND PN.PART_GROUP_ID = NVL(IN_PART_GROUP_ID, PN.PART_GROUP_ID)
ORDER BY PN.PART_NUMBER;
But it will work only if PN.PART_TYPE_ID and PN.PART_GROUP_ID is not null