Why does WHERE clause removes null values from the result? - sql

I have a table I want to filter data from. I tried the following query
SELECT
SIS, COUNT(*)
FROM DL_SQ_DEV_INT.SMRY_DAILY_TRAILER_REPORT
GROUP BY 1;
Result:
BL,17386
EQ,3242
FIFO,5747
GR,15655
HOLD,13035
LT BL,20566
LT GR,14615
LT OR,14190
LT PU,13877
LT YE,13683
null,223376
OR,15727
PI,3563
PU,16105
RW,200
TA,6
tbd,25302
WH,1945
YE,14510
Now when I add a WHERE clause in it, it filters out the null values. The query is a not equal to (<>). How can I avoid that and still have the null values in my result? Changing null to blank or space?
SELECT
SIS, COUNT(*)
FROM DL_SQ_DEV_INT.SMRY_DAILY_TRAILER_REPORT
WHERE UPPER(TRIM(SIS)) <> 'EQ'
GROUP BY 1;
Result:
BL,17386
FIFO,5747
GR,15655
HOLD,13035
LT BL,20566
LT GR,14615
LT OR,14190
LT PU,13877
LT YE,13683
OR,15727
PI,3563
PU,16105
RW,200
TA,6
tbd,25302
WH,1945
YE,14510

Neither "not equal" nor "equal" will select a value that is NULL.
SQL uses "three-way logic" where an expression can be true or false or unknown. NULL is the absence of any value at all so it cannot be equal to something, and if it cannot be equal to a compared value it also cannot be "not equal", instead it is unknown.
To overcome this you need to treat NULL explicitly in your where clause, to include NULLs use OR SIS IS NULL
SELECT
SIS, COUNT(*)
FROM DL_SQ_DEV_INT.SMRY_DAILY_TRAILER_REPORT
WHERE UPPER(TRIM(SIS)) <> 'EQ' OR SIS IS NULL
GROUP BY 1;

You should use this:
SELECT
SIS, COUNT(*)
FROM DL_SQ_DEV_INT.SMRY_DAILY_TRAILER_REPORT
WHERE TRIM(SIS) IS NULL OR UPPER(TRIM(SIS)) <> 'EQ'
GROUP BY 1;
Why does your WHERE clause removes null values from the result: NULL value means the absence of value or value is unknown, so that you can't compare NULL value using scalar value operator, <> 'EQ' will return unknown or not true.
You could refer more post about NULL value in sql in sof, eg this link or search in gg

Related

Concat the values using the case condition

select
case when concat('ACC','-',NVL(trim(bvmo.booking),''),'-',NVL(trim(bvmo.org),''),'-',NVL(trim(bvma.sparm),''),'-',NVL(trim(bvmo.id),'') like 'ACC--%' then
NULL ELSE concatconcat('ACC','-',NVL(trim(bvmo.booking),''),'-',NVL(trim(bvmo.org),''),'-',NVL(trim(bvma.sparm),''),'-',NVL(trim(bvmo.id),'') END AS Parent_id
from bvmo
output:
Parent-id
:----------:
ACC-1123-1344--
ACC-4567-6528--
ACC-7890-9827--
ACC-1143-8079--
ACC-1883-8944--
am expecting as the below output where i can remove the "-" in above case condition in which the values are not appearing in respective columns
Expected output:
Parent-id
:----------:
ACC-1123-1344
ACC-4567-6528
ACC-7890-9827
ACC-1143-8079
ACC-1883-8944
Use concat_ws. It should take care of nulls in the way you wanted.
select
concat_ws('-', 'ACC', trim(bvmo.booking), trim(bvmo.org), trim(bvma.sparm), trim(bvmo.id)) AS Parent_id
from bvmo

`0` values are not shown when I put a string value filter SQL

SELECT DISTINCT ISNULL(a.[BPOAGE], 0) AS BPOAGE, a.[BPOAttic]
FROM [Legacy].[dbo].[MyTables] as a
Result :
SELECT DISTINCT ISNULL(a.[BPOAGE], 0) AS BPOAGE, a.[BPOAttic]
FROM [Legacy].[dbo].[MyTables] as a
where (a.[BPOAGE] not in ('New'))
Result :
Q : Can you tell me why 0 values are not shown when I put this condition a.[BPOAGE] not in ('New')?
Sql works on Three valued logic.It considers NULL as unknown,since it is unknown it will not got selected in the condition you write.If you want to include null rewrite the code as
SELECT DISTINCT ISNULL(a.[BPOAGE], 0) AS BPOAGE,a.[BPOAttic] FROM [Legacy].
[dbo].[MyTables] as a where (a.[BPOAGE] not in ('New') or a.[BPOAGE] is null)

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

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