SQL checking equality inside a case statement inside where clause? - sql

Here is the code:
WHERE 1=1
AND TU.Auction_I IN (41, 42)
AND #StatePickupID = CASE
WHEN #StatePickupID IS NOT NULL
THEN (UP.TransportStateID = #StatePickupID)
END
AND #StateDropoffID = CASE
WHEN #StateDropoffID IS NOT NULL
THEN (UD.TransportStateID = #StateDropoffID)
END
So I only want to return records where UP.TransportStateID is equal to StatePickupID if it is not null, same thing for DropoffID. But I get a syntax error message where the equals sign is and I cannot find any other way to check for equality online. Any help or advice would be much appreciated.

I only want to return records where UP.TransportStateID is equal to StatePickupID if it is not null
This would translate as the following predicate:
#StatePickupID IS NULL OR #StatePickupID = UP.TransportStateID
When the parameter is not null, the predicate filters on TransportStateID; when the parameter is null, the filter is a no-op.
In your where clause, for both parameters :
WHERE 1 = 1
AND TU.Auction_I IN (41, 42)
AND ( #StatePickupID IS NULL OR #StatePickupID = UP.TransportStateID )
AND ( #StateDropoffID IS NULL OR #StateDropoffID = UD.TransportStateID )

Related

How i can return records there are not null only if a column have a determined value

I need to make a query that verify:
if type_answer is equal to Multipla Escolha so i only have to return the records that are not null in correct_answer_description_id
If the type_answer is not equal to Multipla Escolha, don’t make this rule.
So, i try this way:
SELECT * FROM book_unit_question
WHERE book_unit_id = 2
AND status = false
CASE WHEN type_answer = 'Multipla Escolha' THEN
correct_answer_description IS NOT NULL
but i'm getting:
ERROR: syntax error at or near "CASE"
I don't think CASE is the easiest approach here. Can you try the re-written query below?
SELECT * FROM book_unit_question
WHERE book_unit_id = 2
AND status = false
AND (type_answer is null or type_answer != 'Multipla Escolha' or
correct_answer_description IS NOT NULL)
Getting rid of the negative yields negative construct "type_answer is not equal to Multipla Escolha, don’t make this rule" by rephrasing "type answer equal Multipla Escolha then apply this rule. Also applying "only return the records that are not null in correct_answer_description_id". We arrieve at:
select *
from book_unit_question
where book_unit_id = 2
and status = false
and type_answer = 'Multipla Escolha'
and correct_answer_description is not null;

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.

Why 'NOT IN' operator not fetching records for the columns which is not having any value?

I have a table with a column name CORP_SERIOUS,the values of this column can be 1 or 2 or empty. When I am searching unknown values records means empty field using NOT IN operator i am getting the count is zero.
Why the below query is not fetching the records for the field which doesn't have vm.CORP_SERIOUS NOT IN('1','2')?
Here is the Query:
SELECT COUNT(*)
FROM
( SELECT DISTINCT vm.vaer_no vaer,
vm.vaer_no_version version,
vm.priority priority,
vm.case_reported_in reportedIn,
vsr.originalreceivedate initialRcvDate,
vsr.mostrecentinfodate latestRcvDate,
vsr.primarysourcecountry reportingCountry,
vsr.occurcountry occurCountry,
vsrd.primary_source_full_name reporterFullName,
vsrd.sender_full_name senderFullName,
vm.record_id recordId,
vm.notes_flag notesFlag,
vm.dmi_product product,
vmf.VAERS_LINKED,
vm.VAER_STATUS status,
vm.company_unit_name companyunit,
FIND_WF_ACTIVITY(vm.record_id,JBPM_PROCESS_INST_ID),
vmf.CORRESPONDENCE_FLAG corresFlag,
vmf.READ_UNREAD_CORRESPONDENCE readUnreadCorresp,
vm.vaer_mode vmode,
srcDoc.doc_name,
vsr.seriousnessdecision serious,
vm.reportduedate reportduedate,
vm.MANUALLY_LOCKED,
vm.LOCKED_BY,
vm.LOCKED_REASON,
vm.LOCKED_DATE,
vm.vaer_delete,
vm.vaer_nullify nullify,
vm.archived,
vm.COMPLETION_FLAG,
vm.ASSIGNED_USER_GROUP,
COALESCE(vsrd.TEEATESPECIESDECODE,vsrd.SPECIESDECODE,vsrd.OTHERSPECIES,vsrd.TREATEDSPECIES),
COALESCE(vsrd.ANIMAL_BREEDDECODE,vsrd.TREATED_BREEDDECODE,vsrd.ANIMAL_BREED,vsrd.TREATED_BREED),
vm.APPROVED_VAER,
vm.SUBSTANCE_ADDED,
vm.MULTIPLEBREEDADDED,
msg_q.MDN_DATE,
vm.CASE_SOURCE,
vm.MESSAGENUMB,
vsr.NULLIFICATIONREASON,
vm.CREATED_BY,
vm.ASSESSMENT_SOURCE,
vm.ASSESSMENT_CLASSIFICATION,
vm.DMI_VEDDRA_TERM,
vsr.CASEREGISTRATIONTYPE,
vm.AUTHORIZATIONCOMPANY,
vm.E2B_DMI_PRODUCT brandname,
vm.E2B_SUBSTANCE_ADDED e2bSubstanceAdded,
vm.ACCOUNT account,
ACK.record_id ack_recId ,
vm.SUBMITTED_DELAY
FROM agvet_vae_info vm,
agvet_vae_safetyreport vsr,
agvet_vae_safetyreport_detail vsrd,
AGVET_VAE_SOURCE_DOC srcDoc,
AGVET_VAE_FLAGS vmf,
E2B_MESSAGE_QUEUE msg_q,
E2B_MESSAGE_ACK ACK
WHERE vm.fk_avsr_rec_id = vsr.record_id
AND vsr.fk_avsrd_rec_id = vsrd.record_id
AND srcdoc.record_id(+) = vm.fk_vet_source_doc_rec_id
AND vm.IMPORT_FLAG <> 1
AND (vm.DRAFT_SUBMIT_FLAG = 0
OR vm.DRAFT_SUBMIT_FLAG = 2)
AND vm.VAER_NO = vmf.VAER_NO(+)
AND vm.E2B_MESSAGE_LIST_TYPE<>01
AND vm.MESSAGENUMB = msg_q.MESSAGE_NUMBER(+)
AND vm.MESSAGENUMB = ACK.MESSAGE_NUMBER(+)
AND (vm.assigned_to = 48626
OR vm.assigned_to IS NULL
OR vm.assigned_to = 320538
OR vm.assigned_to = 320529
OR vm.assigned_to = 406699)
AND EXISTS
(SELECT *
FROM jbpm_token jt
WHERE jt.node_ IN ( 135,140,146,137,132,129,127,148,144 )
AND jt.processinstance_ = vm.jbpm_process_inst_id
OR vm.jbpm_process_inst_id IS NULL
)
AND ( fn_access_vet_products(48658,vm.RECORD_ID, vm.CASE_REPORTED_IN)=1)
AND (vm.PRIORITY IN ( 02 )
OR vm.PRIORITY IS NULL)
AND ( upper(vm.CORP_SERIOUS) NOT IN ('1','2') )
AND vm.ARCHIVED = 0
AND vm.vaer_nullify = 0
AND vm.vaer_delete = 0
)
The value NULL means unknown.
WHERE vm.CORP_SERIOUS IN('1','2')
is TRUE for '1'
is FALSE for '3'
is NULL for NULL
And
WHERE vm.CORP_SERIOUS NOT IN('1','2')
is NOT TRUE, hence FALSE for '1'
is NOT FALSE hence TRUE for '3'
is NOT NULL, which is again NULL for NULL
As NULL means unknown, we don't know whether the value (that we don't know) is in the given set or not. So the answer is "I don't know", no matter if we ask whether the value is in the list or whether the value is not in the list.
Imagine we don't know John's phone number and I show you some numbers and ask you whether John's number is among them. You can't say yes, you can't say no, you can only say maybe. Same with the DBMS. It cannot tell you TRUE or FALSE, it can only tell you NULL. Now the WHERE clause works like this: The query returns all records for which the given criteria is TRUE. NULL is not TRUE, so the records are not returned.
(Even if NULL itself were in the list, we wouldn't know whether the unknown value in the set is the same as the unknown value in the record. The WHERE clause would still result in NULL. It would make a difference for '3' though: WHERE vm.CORP_SERIOUS NOT IN('1','2', null) would suddenly result in NULL too, because the unknown value in the set could or could not be '3'.)
You could ask: Give me all unknown values plus the values in the list.
WHERE vm.CORP_SERIOUS IS NULL OR vm.CORP_SERIOUS NOT IN('1','2')
Or you could ask:
WHERE NVL(vm.CORP_SERIOUS, 'TREAT AS NOT IN THE LIST') NOT IN('1','2')
(Well, of course the string 'TREAT AS NOT IN THE LIST' must not be in the list then :-)
You can try this query
convert(varchar(50),vm.CORP_SERIOUS) NOT IN('1','2')

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))

Where clause in sql

My sql query is as follows
IF #StatusId = 10
BEGIN
SELECT
*
FROM
Risk AS R
INNER JOIN Statuses AS St ON R.Status_Id=St.Status_Id
WHERE
R.MitigationOwner = COALESCE(#MitigationOwner,R.MitigationOwner)
AND R.RiskFactor = COALESCE(#RiskFactor,R.RiskFactor)
AND R.RiskArea = COALESCE(#RiskArea,R.RiskArea)
AND R.AddedWhen BETWEEN
COALESCE(CONVERT(DATETIME, #StartDate+'00:00:00',120),R.AddedWhen) AND
COALESCE(CONVERT(DATETIME,#EndDate+'23:59:59',120),R.AddedWhen)
END
When I pass only status Id and all other variables are null, then records with NULL MitigationOwner or ModifiedDate are not displayed..
What is wrong in this query?
Use the form:
...
(R.MitigationOwner = #MitigationOwner OR #MitigationOwner IS NULL)
...
This is optimised in SQL Server. COALESCE isn't.
Edit: This does the same as Paul Williams' answer but his answer allows explicit "NULL = NULL" matches. m ylogic is simpler because NULL never equals NULL.
I believe that by ModifiedDate you meant R.AddedWhen
try this:
SELECT
*
FROM
Risk AS R
INNER JOIN Statuses AS St ON R.Status_Id=St.Status_Id
WHERE
(R.MitigationOwner = COALESCE(#MitigationOwner,R.MitigationOwner) OR R.MitigationOwner IS NULL)
AND R.RiskFactor = COALESCE(#RiskFactor,R.RiskFactor)
AND R.RiskArea = COALESCE(#RiskArea,R.RiskArea)
AND (R.AddedWhen BETWEEN
COALESCE(CONVERT(DATETIME, #StartDate+'00:00:00',120),R.AddedWhen) AND
COALESCE(CONVERT(DATETIME,#EndDate+'23:59:59',120),R.AddedWhen) OR R.AddedWhen IS NULL)
If R.MitigationOwner can be null, then your comparison clause:
WHERE
R.MitigationOwner = COALESCE(#MitigationOwner,R.MitigationOwner)
Must be rewritten to handle NULL values:
WHERE
((R.MitigationOwner IS NULL AND #MitigationOwner IS NULL)
OR (R.MitigationOwner = #MitigationOwner))
See this article on Wikipedia about NULL.