using a searched case in where condition - sql

I recently got this stored procedure where it is using a variable called #marketCode. The application is passing either South or null for this variable.
In my select statement, I want to retrieve every market except South if the application passes null.
and marketCode =! 'South'
If the application passes a non null value, then I will use that one instead.
and marketCode = 'North'
How can I join these two into one case?
AND marketCode = (case #marketCode when null then <..not equal to 'South'..>
else <..equal to 'South'..> end )

You should be able to do this with an OR condition:
...
AND (
(#marketCode IS NULL AND marketCode <> 'South')
OR
(#marketCode IS NOT NULL AND marketCode = #marketCode)
)

Related

change where condition based on column value

I faced the following requirement. The following query is called by a procedure. The value p_pac_code is the input parameter of the procedure.
The requirement is the query should have an additional condition sp_sbsp.SUBSPCLTY_CODE!='C430 if the p_pac_code value is '008'.
For any other p_pac_code value, it should run as it is below. Is there way to do this by adding an additional condition in the WHERE clause?
As for now, I have done this using IF.....ELSE using the query two times separately depending on p_pac_code value. But I am required to find a way to do with just adding a condition to this single query.
SELECT ptg.group_cid
FROM PRVDR_TYPE_X_SPCLTY_SUBSPCLTY ptxss,
PT_X_SP_SSP_STATUS pxsst ,
pt_sp_ssp_x_group ptg,
group_x_group_store gg,
specialty_subspecialty sp_sbsp,
treatment_type tt,
provider_type pt
WHERE
pt.PRVDR_TYPE_CODE = ptxss.PRVDR_TYPE_CODE
AND tt.TRTMNT_TYPE_CODE = pxsst.TRTMNT_TYPE_CODE
AND ptxss.PRVDR_TYPE_X_SPCLTY_SID = pxsst.PRVDR_TYPE_X_SPCLTY_SID
AND tt.TRTMNT_TYPE_CODE = p_pac_code
AND TRUNC(SYSDATE) BETWEEN TRUNC(PXSST.FROM_DATE) AND TRUNC(PXSST.TO_DATE)
AND ptg.prvdr_type_code =ptxss.prvdr_type_code
AND ptg.spclty_subspclty_sid = ptxss.spclty_subspclty_sid
AND ptxss.spclty_subspclty_sid = sp_sbsp.spclty_subspclty_sid
AND ptg.spclty_subspclty_sid = sp_sbsp.spclty_subspclty_sid
AND ptg.status_cid = 2
AND ptg.group_cid = gg.group_cid
AND gg.group_store_cid = 16
AND gg.status_cid = 2;
Thanks in advance.
You can simply add a condition like this:
... and (
( sp_sbsp.SUBSPCLTY_CODE!='C430' and p_pac_code = '008')
OR
NVL(p_pac_code, '-') != '008'
)
This can be re-written in different ways, this one is quite self-explanatory
Just add:
AND NOT ( NVL( sp_sbsp.SUBSPCLTY_CODE, 'x' ) = 'C430'
AND NVL( p_pac_code value, 'x' ) = '008' )
to the where clause.
The NVL function is used so that it will match NULL values (if they exist in your data); otherwise, even though NULL does not match C430 you will still find that NULL = 'C430' and NULL <> 'C430' and NOT( NULL = 'C430' ) will all return false.
Quite easy. Add the following condition:
AND (sp_sbsp.SUBSPCLTY_CODE != 'C430' OR p_pac_code value != '008')
(don't forget the parenthesis)
Just sharing
SELECT ptg.group_cid
FROM PRVDR_TYPE_X_SPCLTY_SUBSPCLTY ptxss
WHERE
pt.PRVDR_TYPE_CODE = ptxss.PRVDR_TYPE_CODE
&&((tt.TRTMNT_TYPE_CODE = pxsst.TRTMNT_TYPE_CODE)
or (tt.TRTMNT_TYPE_CODE = pxsst.TRTMNT_TYPE_CODE))
just use the parenthesis to specify where the conditionmust implement.

How to give change working of having function dynamicaly on executing an sql statement?

I'm having a Sql code like as follows
Select a.ItemCode, a.ItemDesc
From fn_BOM_Material_Master('A', #AsOnDate, #RptDate, #BranchID, #CompID)a
Left Outer Join fn_INV_AsOnDate_Stock(#StockDate, #AsOnDate, #RptDate, #BranchID, #CompID, #Finyear)b
On a.ItemCode=b.ItemCode and b.WarehouseCode<>'WAP'
and a.BranchID=b.BranchID and a.CompID=b.COmpID
Where a.ItemNatureCode = 'F' and a.BranchID = #BranchID and a.CompID = #CompID
Group by a.ItemCode, a.ItemDesc
Having sum(b.CBQty)<=0
Here the problem is that im passing an "#ShowZeroStock" value as as bit if the "#ShowZeroStock" value is '1' then Having should not be validated or (i.e: All values from the table should be returned including zero)
So How to change the query based on passed bit value "#ShowZeroStock"
I can Use "If else " condition at the top and remove having in else part, but for a lengthy query i can't do the same.
Is this the logic you want?
Having sum(b.CBQty) <= 0 or #ShowZeroStock = 1

SQL: field = other_field returns false even if they are identical (NULL values)

I have a difficulty because when comparing two fields in a subquery, although the fields are identical i.e. they both have NULL values, the comparison returns a FALSE result
Therfore NULL = NULL is returning FALSE
Now I know that NULLs are supposed to be compared with the IS operator, however when I compare two fields how am I supposed to know they contain a null? I need to compare two fields for identical data both if the values are NULL or not.
Consider this SQL:
SELECT
*
FROM
fts.fts_customers_data_50360001
WHERE
fts.fts_customers_data_50360001.record_type = 15
AND
fts.fts_customers_data_50360001.mid = 103650360001
AND NOT EXISTS
(
SELECT
fts.temp_fees_50360001.record_type
FROM
fts.temp_fees_50360001
WHERE
fts.temp_fees_50360001.record_type = fts.fts_customers_data_50360001.record_type
AND
fts.temp_fees_50360001.merch_id = fts.fts_customers_data_50360001.mid
AND
fts.temp_fees_50360001.fee_curr = fts.fts_customers_data_50360001.currency
AND
fts.temp_fees_50360001.card_scheme = fts.fts_customers_data_50360001.card_scheme
AND
fts.temp_fees_50360001.tran_type = fts.fts_customers_data_50360001.fee_type
AND
fts.temp_fees_50360001.area = fts.fts_customers_data_50360001.region
AND
fts.temp_fees_50360001.srvc_type = fts.fts_customers_data_50360001.card_type
);
In the query above,
fts.temp_fees_50360001.card_scheme = fts.fts_customers_data_50360001.card_scheme
both have NULL values inside but the comparison returns false .. too bad
ANY IDEAS WOULD BE MUCH APPRECIATED
As the others have pointed out, NULL cannot be compared with NULL.
In Postgres you can shorten your expressions by using the operator IS DISTINCT FROM which is a null-safe replacement for <>. In your case you'd need to use IS NOT DISTINCT FROM to compare for equality (looks a bit the wrong way round but unfortunately there is no corresponding IS EQUAL TO defined in the SQL standard).
From the manual:
Ordinary comparison operators yield null (signifying "unknown"), not true or false, when either input is null. For example, 7 = NULL yields null, as does 7 <> NULL. When this behavior is not suitable, use the IS [ NOT ] DISTINCT FROM constructs:
So, instead of
(fts.temp_fees_50360001.record_type = fts.fts_customers_data_50360001.record_type
OR (fts.temp_fees_50360001.record_type IS NULL
AND fts.fts_customers_data_50360001.record_type IS NULL)
)
you can use:
(fts.temp_fees_50360001.record_type IS NOT DISTINCT FROM fts.fts_customers_data_50360001.record_type)
to handle NULL values automatically. The condition looks a bit strange if you want to compare for equality but it still is quite short.
First of all, use aliases for your tables, your query will be MUCH more readable:
select *
from fts.fts_customers_data_50360001 as d
where
d.record_type = 15 and
d.mid = 103650360001 and
not exists
(
select *
from fts.temp_fees_50360001 as f
where
f.record_type = d.record_type and
f.merch_id = d.mid and
f.fee_curr = d.currency and
f.card_scheme = d.card_scheme and
f.tran_type = d.fee_type and
f.area = d.region and
f.srvc_type = d.card_type
)
As for your question, there's several ways to do this, for example, you can use syntax like this:
...
(
f.card_scheme is null and d.card_scheme is null or
f.card_scheme = d.card_scheme
)
...
Or use coalesce with some value that couldn't be stored in your column:
...
coalesce(f.card_scheme, -1) = coalesce(d.card_scheme, -1)
...
Recently I also like using exists with intersect for this type of comparisons:
...
exists (select f.card_scheme, f.tran_type intersect select d.card_scheme, d.tran_type)
...
Just a side note - you have to be careful when writing queries like this and check query plans to be sure your indexes are used.
In SQL, null is never equal to null. The only way to get a true result for a comparison with null is via the special tests:
IS NULL
IS NOT NULL
In your case, you must cater specifically for the "two nulls" case being considered equal:
AND (fts.temp_fees_50360001.card_scheme = fts.fts_customers_data_50360001.card_scheme
OR (fts.temp_fees_50360001.card_scheme IS NULL
AND fts.fts_customers_data_50360001.card_scheme IS NULL)
)
There's no getting around dealing with it (although there are a few variations).
The following inner SELECT works (but I give no guarantee regarding performance):
SELECT
fts.temp_fees_50360001.record_type
FROM
fts.temp_fees_50360001
WHERE
(fts.temp_fees_50360001.record_type = fts.fts_customers_data_50360001.record_type
OR (fts.temp_fees_50360001.record_type IS NULL AND fts.fts_customers_data_50360001.record_type IS NULL))
AND
(fts.temp_fees_50360001.merch_id = fts.fts_customers_data_50360001.mid
OR (fts.temp_fees_50360001.merch_id IS NULL AND fts.fts_customers_data_50360001.mid IS NULL))
AND
(fts.temp_fees_50360001.fee_curr = fts.fts_customers_data_50360001.currency
OR (fts.temp_fees_50360001.fee_curr IS NULL AND fts.fts_customers_data_50360001.currency IS NULL))
AND
(fts.temp_fees_50360001.card_scheme = fts.fts_customers_data_50360001.card_scheme
OR (fts.temp_fees_50360001.card_scheme IS NULL AND fts.fts_customers_data_50360001.card_scheme IS NULL))
AND
(fts.temp_fees_50360001.tran_type = fts.fts_customers_data_50360001.fee_type
OR (fts.temp_fees_50360001.tran_type IS NULL AND fts.fts_customers_data_50360001.fee_type IS NULL))
AND
(fts.temp_fees_50360001.area = fts.fts_customers_data_50360001.region
OR (fts.temp_fees_50360001.area IS NULL AND fts.fts_customers_data_50360001.region IS NULL))
AND
(fts.temp_fees_50360001.srvc_type = fts.fts_customers_data_50360001.card_type
OR (fts.temp_fees_50360001.srvc_type IS NULL AND fts.fts_customers_data_50360001.card_type))

Conditional Sql in Daisy chained Query

I have one master table with all the IDs to each child table. The SQL statement looks like this...
SELECT Class.Descript
, Regulation.Descript AS Reg
, Compgroup.Descript AS Grouping
, Category.Descript AS Cat
, Exempt.Descript AS Exempt
, Reason.Descript AS Reasons
, COALESCE(ComponentRuleSet.NormalType, ComponentRuleSet.Supertype, '') AS Type
FROM ComponentRuleSet
LEFT OUTER JOIN Reason
ON ComponentRuleSet.ComponentCategoryID = Reason.ComponentCategoryID
LEFT OUTER JOIN Class
ON ComponentRuleSet.ComponentClassID = Class.ComponentClassID
LEFT OUTER JOIN Regulation
ON ComponentRuleSet.RegulationID = Regulation.RegulationID
LEFT OUTER JOIN Compgroup
ON ComponentRuleSet.ComplianceGroupID = Compgroup.ComplianceGroupID
LEFT OUTER JOIN Category
ON ComponentRuleSet.ComponentCategoryID = Category.ComponentCategoryId
LEFT OUTER JOIN Exempt
ON ComponentRuleSet.ExemptID = Exempt.ComponentExemptionID
WHERE (ComponentRuleSet.ComponentID = 38048)
The problem is that there are two fields in the ComponentRuleSet table called NormalType and Supertype. If either of those fields have a value, I need to display it in a column called Type. Yet, if neither have a value I need to display a Blank value in the Type column.
Any ideas?
---EDIT
Is my placement of COALESCE correct in the edited query? It is still returning errors.
--UPDATE
IMPORTANT: The type of both fields are boolean, I need to return the column name of the column that holds a TRUE value, and place that value in the TYPE column.
Use COALESCE for this field:
COALESCE(ComponentRuleSet.NormalType, ComponentRuleSet.Supertype, '') AS Type
COALESCE:
Returns the first nonnull expression among its arguments.
Following your comments as to the actual requirement, CASE is probably a better option:
CASE WHEN ComponentRuleSet.NormalType = 1 THEN 'NormalType'
WHEN ComponentRuleSet.Supertype = 1 THEN 'SuperType'
ELSE ''
END AS Type
Seeing your comments, perhaps a CASE expression will work:
select ...
, CASE WHEN ComponentRuleSet.NormalType is not null then 'NormalType'
WHEN ComponentRuleSet.Supertype is not null then 'SuperType'
ELSE ''
end as Type
UPDATE Since boolean values are just 1 for true and 0 for false, try this:
select ...
, CASE WHEN ComponentRuleSet.NormalType = 1 then 'NormalType'
WHEN ComponentRuleSet.Supertype = 1 then 'SuperType'
ELSE ''
end as Type

Modify Return Value of SELECT-Statement (TSQL) [Optimizing query]

Problem:
A Database collumn has a Tristate (0,1,2).
Each of the values are used serversidely.
The Clientcode (which cant be changed anymore) is only able to understand '0,1'.
In the Clients view '1' is identic with '2'. So I want to change the SQL Query in the Database to return '1', if the specific value is > 0.
My current Solution is combining 2 Selects (using UNION SELECT) with different WHERE-Clauses and returning '1' or '0' as static values. Now I'm looking for a solution to 'translate' the value within only ONE SELECT statement.
This is my current Solution:
SELECT
dbo.Nachricht.NachrichtID, dbo.Nachricht.Bezeichnung, '1' AS BetrifftKontoeinrichtung,
FROM dbo.Nachricht INNER JOIN dbo.AdditionalData
ON dbo.Nachricht.NachrichtID = dbo.AdditionalData.NachrichtID
WHERE (dbo.Nachricht.NachrichtID in ( 450,439 ))
AND dbo.AdditionalData.BetrifftKontoeinrichtung > 0
UNION SELECT
dbo.Nachricht.NachrichtID, dbo.Nachricht.Bezeichnung, '0' AS BetrifftKontoeinrichtung,
FROM dbo.Nachricht INNER JOIN dbo.AdditionalData
ON dbo.Nachricht.NachrichtID = dbo.AdditionalData.NachrichtID
WHERE (dbo.Nachricht.NachrichtID in ( 450,439 ))
AND dbo.AdditionalData.BetrifftKontoeinrichtung = 0
You can use a case statement, like this:
SELECT
dbo.Nachricht.NachrichtID, dbo.Nachricht.Bezeichnung,
CASE WHEN dbo.AdditionalData.BetrifftKontoeinrichtung = 0
THEN '0' ELSE '1'
END AS BetrifftKontoeinrichtung,
FROM dbo.Nachricht
INNER JOIN dbo.AdditionalData
ON dbo.Nachricht.NachrichtID = dbo.AdditionalData.NachrichtID
WHERE (dbo.Nachricht.NachrichtID in ( 450,439 ))
Looks like you need to use CASE. A decent tutorial here
http://www.databasejournal.com/features/mssql/article.php/3288921/T-SQL-Programming-Part-5---Using-the-CASE-Function.htm
See the worked example
If you just CAST(CAST(val AS BIT) AS INT) you will get integer 0 for 0 and integer 1 for everything else.