Include NULL values in a designated field in my where clause on SSRS - sql

I am learning SQL so be gentle. If I have designated a specific role in my where clause it is only pulling those cases where that role is populated. How can I also include the NULL values or those roles that are blank?
Here is the where clause now:
WHERE (dbo.vcases.lawtype = 'My Cases') AND
(dbo.vcase_parties_people.role_sk = 4001) AND
**(v1.role_sk = 3940) AND
(v1.report_ind = 'Y') AND
(v2.role_sk = 3939) AND
(v2.report_ind = 'Y')** AND
(dbo.vcases.case_type NOT IN ('Case type 1', 'Case type 2'))

The COALESCE() expression in SQL is useful for substituting a default value when NULL is encountered for a given column or expression. When the query optimizer encounters a COALESCE() call, it will internally rewrite that expression to an equivalent CASE...WHEN expression. In your sample query, WHERE (COALESCE(v1.role_sk, 3940) = 3940) would operate (and optimize) the same as WHERE (CASE WHEN v1.role_sk IS NOT NULL THEN v1.role_sk ELSE 3940 END = 3940).
Since your example specifically involves a condition in the WHERE clause, you may want to use an OR operation, which could optimize better than a COALESCE() expression: WHERE (v1.role_sk = 3940 OR v1.role_sk IS NULL).
This is also assuming that any joins in your query aren't filtering out rows whose role_sk column is NULL.

You might edit your code as follows:
WHERE (dbo.vcases.lawtype = 'My Cases') AND
(dbo.vcase_parties_people.role_sk = 4001) AND
(v1.role_sk = 3940 OR v1.role_sk IS NULL) AND
(v1.report_ind = 'Y') AND
(v2.role_sk = 3939) AND
(v2.report_ind = 'Y') AND
(dbo.vcases.case_type NOT IN ('Case type 1', 'Case type 2'))
The use of the Coalesce function has been suggested but a good rule of thumb in SQL is to avoid the use of functions in the WHERE clause because it reduces the efficiency of the table's indexes. Functions in WHERE clause often cause Index-Scans instead of the more efficient Index-Seeks.

Related

How to write an Open SQL statement with substring in the JOIN ON condition? [duplicate]

I have the following select statement in ABAP:
SELECT munic~mandt VREFER BIS AB ZZELECDATE ZZCERTDATE CONSYEAR ZDIMO ZZONE_M ZZONE_T USAGE_M USAGE_T M2MC M2MT M2RET EXEMPTMCMT EXEMPRET CHARGEMCMT
INTO corresponding fields of table GT_INSTMUNIC_F
FROM ZCI00_INSTMUNIC AS MUNIC
INNER JOIN EVER AS EV on
MUNIC~POD = EV~VREFER(9).
"where EV~BSTATUS = '14' or EV~BSTATUS = '32'.
My problem with the above statement is that does not recognize the substring/offset operation on the 'ON' clause. If i remove the '(9) then
it recognizes the field, otherwise it gives error:
Field ev~refer is unknown. It is neither in one of the specified tables
nor defined by a "DATA" statement. I have also tried doing something similar in the 'Where' clause, receiving a similar error:
LOOP AT gt_instmunic.
clear wa_gt_instmunic_f.
wa_gt_instmunic_f-mandt = gt_instmunic-mandt.
wa_gt_instmunic_f-bis = gt_instmunic-bis.
wa_gt_instmunic_f-ab = gt_instmunic-ab.
wa_gt_instmunic_f-zzelecdate = gt_instmunic-zzelecdate.
wa_gt_instmunic_f-ZZCERTDATE = gt_instmunic-ZZCERTDATE.
wa_gt_instmunic_f-CONSYEAR = gt_instmunic-CONSYEAR.
wa_gt_instmunic_f-ZDIMO = gt_instmunic-ZDIMO.
wa_gt_instmunic_f-ZZONE_M = gt_instmunic-ZZONE_M.
wa_gt_instmunic_f-ZZONE_T = gt_instmunic-ZZONE_T.
wa_gt_instmunic_f-USAGE_M = gt_instmunic-USAGE_M.
wa_gt_instmunic_f-USAGE_T = gt_instmunic-USAGE_T.
temp_pod = gt_instmunic-pod.
SELECT vrefer
FROM ever
INTO wa_gt_instmunic_f-vrefer
WHERE ( vrefer(9) LIKE temp_pod ). " PROBLEM WITH SUBSTRING
"AND ( BSTATUS = '14' OR BSTATUS = '32' ).
ENDSELECT.
WRITE: / sy-dbcnt.
WRITE: / 'wa is: ', wa_gt_instmunic_f.
WRITE: / 'wa-ever is: ', wa_gt_instmunic_f-vrefer.
APPEND wa_gt_instmunic_f TO gt_instmunic_f.
WRITE: / wa_gt_instmunic_f-vrefer.
ENDLOOP.
itab_size = lines( gt_instmunic_f ).
WRITE: / 'Internal table populated with', itab_size, ' lines'.
The basic task i want to implement is to modify a specific field on one table,
pulling values from another. They have a common field ( pod = vrefer(9) ). Thanks in advance for your time.
If you are on a late enough NetWeaver version, it works on 7.51, you can use the OpenSQL function LEFT or SUBSTRING. Your query would look something like:
SELECT munic~mandt VREFER BIS AB ZZELECDATE ZZCERTDATE CONSYEAR ZDIMO ZZONE_M ZZONE_T USAGE_M USAGE_T M2MC M2MT M2RET EXEMPTMCMT EXEMPRET CHARGEMCMT
FROM ZCI00_INSTMUNIC AS MUNIC
INNER JOIN ever AS ev
ON MUNIC~POD EQ LEFT( EV~VREFER, 9 )
INTO corresponding fields of table GT_INSTMUNIC_F.
Note that the INTO clause needs to move to the end of the command as well.
field(9) is a subset operation that is processed by the ABAP environment and can not be translated into a database-level SQL statement (at least not at the moment, but I'd be surprised if it ever will be). Your best bet is either to select the datasets separately and merge them manually (if both are approximately equally large) or pre-select one and use a FAE/IN clause.
They have a common field ( pod = vrefer(9) )
This is a wrong assumption, because they both are not fields, but a field an other thing.
If you really need to do that task through SQL, I'll suggest you to check native SQL sentences like SUBSTRING and check if you can manage to use them within an EXEC_SQL or (better) the CL_SQL* classes.

Snowflake ignores statement in where clause where I'm comparing timestamps

so I'm building a SCD type 2 in snowflake, but it ignores the where clause in which is comparision between "to_timestamp" and "expiry_date". Expiry_date is a variable that is set to '9999-08-17 07:31:29.901000000' (as infinity) and To_timestamp is a column in table. I want to query only the rows that have to_timestamp set to infinity (they are still active) but snowflake seems to ignore this part of where clause. Below is some of the code (it should update the rows that are expired - that means change their "to_timestamp" to current time. and it does but it does to rows with timestamps of all kind - it ignores last line)
SET EXPIRY_DATE_NTZ = '9999-08-17 07:31:29.901000000';
SET CURRENT_DATE_NTZ = TO_TIMESTAMP_NTZ(CURRENT_TIMESTAMP());
UPDATE CUSTOMER_TARGET CT
SET CT.TO_TIMESTAMP = $CURRENT_DATE_NTZ
FROM POC.SNOWFLAKE_POC.CUSTOMER_STAGE CS
WHERE CT.C_CUSTOMER_ID = CS.C_CUSTOMER_ID
AND (CT.C_FIRST_NAME <> CS.C_FIRST_NAME OR CT.C_LAST_NAME <> CS.C_LAST_NAME OR CT.C_BIRTH_YEAR
<> CS.C_BIRTH_YEAR OR CT.C_BIRTH_COUNTRY <> CS.C_BIRTH_COUNTRY OR CT.C_LAST_REVIEW_DATE<>CS.C_LAST_REVIEW_DATE)
AND CT.TO_TIMESTAMP = $EXPIRY_DATE_NTZ;
I have two of these update statements (one for updates and one for deletes) and a merge statement for inserts. And it ignores the comparision in every single one, updating the rows that have "to_timestamp" set to something like "2021-08-24 07:11:53.510000000". I've tried every combination possible (between ... and ..., >= ... <=, <=, >=, comparing in "case" statement of update,...) - nothing. What could be the cause/solution?
As we do not know the structure of CUSTOMER_TARGET I would suggest to explicitly set the data type of EXPIRY_DATE_NTZ variable to match the column data type:
SET EXPIRY_DATE_NTZ = '9999-08-17 07:31:29.901000000';
SELECT $EXPIRY_DATE_NTZ;
DESCRIBE RESULT LAST_QUERY_ID();
to:
-- TIMESTAMP_NTZ as an example
SET EXPIRY_DATE_NTZ = '9999-08-17 07:31:29.901000000'::TIMESTAMP_NTZ;
SELECT $EXPIRY_DATE_NTZ;
DESCRIBE RESULT LAST_QUERY_ID();
By doing that way there are no "implicit conversions" involved in the process.
Another advice is usage of IS DISTINCT FROM instead of <>. IS DISTINCT FROM is NULL safe, which is important if columns are defined as nullable.
UPDATE CUSTOMER_TARGET CT
SET CT.TO_TIMESTAMP = $CURRENT_DATE_NTZ
FROM POC.SNOWFLAKE_POC.CUSTOMER_STAGE CS
WHERE CT.C_CUSTOMER_ID = CS.C_CUSTOMER_ID
AND (CT.C_FIRST_NAME IS DISTINCT FROM CS.C_FIRST_NAME
OR CT.C_LAST_NAME IS DISTINCT FROM CS.C_LAST_NAME
OR CT.C_BIRTH_YEAR IS DISTINCT FROM CS.C_BIRTH_YEAR
OR CT.C_BIRTH_COUNTRY IS DISTINCT FROM CS.C_BIRTH_COUNTRY
OR CT.C_LAST_REVIEW_DATE IS DISTINCT FROM CS.C_LAST_REVIEW_DATE)
AND CT.TO_TIMESTAMP = $EXPIRY_DATE_NTZ;
Your SQL does not have any issues with the filters (ORs are surrounded by the brackets etc). I assume that you have checked the execution profile, and did not see your filter (CT.TO_TIMESTAMP = '9999-08-17 07:31:29.901000000'). In this case, all rows in the target table should have this value in the column TO_TIMESTAMP.
I highly recommend you check the data first. If you are running multiple UPDATE/MERGE commands, you may miss that the data has already updated with this value.

Add conditions where with 2 field conditions do not run accurately

The data that appears does not match the conditions that have been applied
I implemented SQL code in the Navicat application, and have changed the structure of the code several times but it still doesn't work,
data that is not of ilart condition type
still appears
SELECT SERMAT,ILART,sum(GKSTP) as jumlah
FROM swift_zab_iw39
WHERE ILART='OVH' OR ILART='TST' and SERMAT='024147-000:09052'
GROUP BY ILART,SERMAT
Use IN operator:
WHERE ILART IN('OVH','TST') AND SERMAT = '024147-000:09052'
Add parenthesis to the OR condition in the WHERE clause as:
WHERE (ILART = 'OVH' OR ILART = 'TST') AND SERMAT = '024147-000:09052'

Handle null values within SQL IN clause

I have following sql query in my hbm file. The SCHEMA, A and B are schema and two tables.
select
*
from SCHEMA.A os
inner join SCHEMA.B o
on o.ORGANIZATION_ID = os.ORGANIZATION_ID
where
case
when (:pass = 'N' and os.ORG_ID in (:orgIdList)) then 1
when (:pass = 'Y') then 1
end = 1
and (os.ORG_SYNONYM like :orgSynonym or :orgSynonym is null)
This is a pretty simple query. I had to use the case - when to handle the null value of "orgIdList" parameter(when null is passed to sql IN it gives error). Below is the relevant java code which sets the parameter.
if (_orgSynonym.getOrgIdList().isEmpty()) {
query.setString("orgIdList", "pass");
query.setString("pass", "Y");
} else {
query.setString("pass", "N");
query.setParameterList("orgIdList", _orgSynonym.getOrgIdList());
}
This works and give me the expected output. But I would like to know if there is a better way to handle this situation(orgIdList sometimes become null).
There must be at least one element in the comma separated list that defines the set of values for the IN expression.
In other words, regardless of Hibernate's ability to parse the query and to pass an IN(), regardless of the support of this syntax by particular databases (PosgreSQL doesn't according to the Jira issue), Best practice is use a dynamic query here if you want your code to be portable (and I usually prefer to use the Criteria API for dynamic queries).
If not need some other work around like what you have done.
or wrap the list from custom list et.

optional parameter checking in where clauses

I have a bunch of report parameters and as a result my criteria checking first checks if parameter value is null and if not compares it with a column value .
(#dateStart IS NULL OR #dateStart <= BELGE.AccDate)
AND (#dateEnd IS NULL OR #dateEnd >= BELGE.AccDate)
AND (#CompanyId IS NULL OR #CompanyId = hrktlr.CompanyId)
AND ((#onKayitlarDahil = 1 and hrktlr.StatusCode in ('M', 'O'))
OR (#onKayitlarDahil = 0 AND hrktlr.StatusCode = 'M'))
AND (#BizPartnerId IS NULL or CK.BizPartnerId = #BizPartnerId)
AND (#BizPartnerKodStart is null or #BizPartnerKodStart = '' or #BizPartnerKodStart <= CK.BizPartnerKod)
AND (#BizPartnerKodEnd is null or #BizPartnerKodEnd = '' or #BizPartnerKodEnd >= CK.BizPartnerKod)
AND (#BizPartnerType is null or #BizPartnerType=CK.BizPartnerType)
this is great for a maintainable sql query, but the problem is that Sql Query Optimizer prepares itself for the worst case I guess, and index usage is bad. For example when I pass in BizPartnerId and thus avoid BizPartnerId is null check, query runs a 100 times faster.
So if I keep going with this approach are there any pointers that you can recommend for Query Planner to help increase query performance.
Any viable alternatives to optional parameter checking?
To stop sql server form saving a sub optimal query plan you can use the option WITH RECOMPILE. The query plan will be recalculated each time you run the query.