how to use four different AND condition in single soql query? - salesforce

I have two soql on same object but where condition is vary by single condition mentioned below, I need to combine both and make it as single soql, can someone help me how to do with below soql after where conditions?
1st one have contact.Contact_ID__c != null and 2nd one have Roles != null.I need to combine both in single soql
1st Query:
SELECT
Id,
Roles,
contact.contact_Id__c,
Account.Id,
account.customer_Id__c,
Relationship_End_Date__c,
IsActive
FROM
AccountContactRecord
WHERE
account.customer_Id__c != null AND contact.Contact_ID__c != null AND Id in: conList
2nd Query:
SELECT
Id,
Roles,
contact.Contact_ID__c,
Account.Id,
account.customer_Id__c,
Ownership__c
FROM
AccountContactRecord
WHERE
account.customer_Id__c != null AND Roles != null AND Id in: conList

Two of the conditions are identical so it's not very hard. Try to put most selective conditions first (filter by Id, by lookup, by any indexed field), good for performance.
where account.customer_Id__c != null and contact.Contact_ID__c != null and Id IN:conList
+
where account.customer_Id__c != null and Roles != null and Id IN:conList
becomes
WHERE Id IN:conList
AND Account.Customer_Id__c != null
AND (Contact.Contact_ID__c != null OR Roles != null)

Related

How does not equal in snowflake exactly work?

I have a snowflake query that has a field called status. The field either contains null or 'deleted'
when I do the following to get only deleted it works:
select * from tbl_1 where status = 'deleted'
when I try excluding all deleted it excludes everything, no records are returned. Here's what I've tried
select * from tbl_1 where status != 'deleted'
select * from tbl_1 where status <> 'deleted'
Neither one works. Can someone tell me why or what's the proper way of doing this in snowflake?
Thanks in advance!
I think you should use EQUAL_NULL here. EQUAL_NULL Compares whether two expressions are equal. The function is NULL-safe, meaning it treats NULLs as known values for comparing equality. Note that this is different from the EQUAL comparison operator (=), which treats NULLs as unknown values.
https://docs.snowflake.com/en/sql-reference/functions/equal_null.html#equal-null
CREATE TABLE NULL_TEST(PRODUCT VARCHAR, STATUS VARCHAR);
INSERT INTO NULL_TEST VALUES('1111','DELETED');
INSERT INTO NULL_TEST VALUES('1112',NULL);
select * from NULL_TEST where NOT EQUAL_NULL(status,'DELETED');
You can try the following which factors for the status being null and unsearchable for you.
select * from tbl_1 where IS_NULL_VALUE(status:no_value) != 'deleted'
https://docs.snowflake.com/en/sql-reference/functions/is_null_value.html
Use NVL as it simply converts the NULL to another value that you can compare against
NVL doc here
I've tested using the below query to return values 2, 3 (that are not 'deleted')
Select *
from
values (1,'deleted'),(2,NULL),(3,null),(4,'deleted')
WHERE NVL($2,'N/A')!='deleted';
So for your case use SQL
select * from tbl_1 where NVL(status,'N/A') != 'deleted';

Need to make NULL=Value evaluate to TRUE

I have a dimension table I'm trying to create that would require records with NULLs to be overwritten by a value when all other non-null fields match.
This logic works and shows what I mean by "null=Value evaluates to TRUE":
UPDATE A
SET
A.SSN = COALESCE(A.SSN, B.SSN)
,A.DOB = COALESCE(A.DOB, B.DOB)
,A.ID_1 = COALESCE(A.ID_1, B.ID_1)
,A.ID_2 = COALESCE(A.ID_2, B.ID_2)
,A.ID_3 = COALESCE(A.ID_3, B.ID_3)
,A.ID_4 = COALESCE(A.ID_4, B.ID_4)
FROM #TESTED1 A
INNER JOIN #TESTED1 B
ON (A.SSN = B.SSN
OR A.SSN IS NULL
OR B.SSN IS NULL)
AND (A.DOB = B.DOB
OR A.DOB IS NULL
OR B.DOB IS NULL)
AND (A.ID_1 = B.ID_1
OR A.ID_1 IS NULL
OR B.ID_1 IS NULL)
AND (A.ID_2 = B.ID_2
OR A.ID_2 IS NULL
OR B.ID_2 IS NULL)
AND (A.ID_3 = B.ID_3
OR A.ID_3 IS NULL
OR B.ID_3 IS NULL)
AND (A.ID_4 = B.ID_4
OR A.ID_4 IS NULL
OR B.ID_4 IS NULL)
WHERE A.ArbitraryTableID <> B.ArbitraryTableID
but takes exponentially longer the more records that are evaluated, 10k records takes 9sec, 100k records takes 9min, etc. I'm trying to do an initial load of around 30mil records and then I will have to evaluate the entire table in a MERGE operation with another 10k records every day.
For example I would need the following three rows (that all exist on the same table) to combine into two rows with all values populated:
Just like this:
Unfortunately members can have multiple IDs so I can't count on any one of these IDs to be unique or even exist at all to cut down on my join conditions.
For performance of this query, make sure you have an index sorting all the criteria you are making your join on.
I did a quick example of what you described:
`declare #test table (
row_name NVARCHAR(50),
id1 int null,
id2 int null,
id3 int null
)
insert into #test values('row1', 1,2,3), ('row2',1,4,5), ('row3',11,null,null), ('row4',null,4,null), ('row5',3,6,5), ('row6',3,null,null)
select *
from #test t1
inner join #test t2 on (
(t1.id1 = t2.id1
or t1.id1 is null
or t2.id1 is null)
and (
t1.id2 = t2.id2
or t1.id2 is null
or t2.id2 is null)
and (
t1.id3 = t2.id3
or t1.id3 is null
or t2.id3 is null)
)
where t1.row_name <> t2.row_name
order by t1.row_name`
There are a couple of possible problems I see in my test output:
row3 and row4 in my example match because they have none of the same IDs. I'm guessing this is not desired but if you really have several independent systems with different keys, is it possible that you have a lot of rows that fall into this scenario? Every row with id1 set and no other keys and every row with id2 set and no other keys will match.
row1 and row4 do not match even though they should through transitivity (row1.id1 -> row2.id1, row2.id2-> row4.id2)
Based on your response to my comment, I suggest the following solution:
a master record identifying the member/customer
child records for each master record storing the respective IDs
Replace your UPDATE statement with
INSERTs into the master table for all records in table A that are guaranteed to be unique (e.g. SSN).
INSERTs into the child table for all records in table A with not-NULL ID attributes
mark records in table A as processed by UPDATEing a foreign key column referencing the master records IDENTITY primary key
INSERT into the child table all records from A that you can safely assign to existing master records, and again set the FK
This solution would resolve the performance issues resulting from a 5-way JOIN, and also mark processed source records as processed.

Ignore condition in WHERE clause when column is NULL

I do have table were one row (with Type =E) is related to another row.
I have written query to return COUNT of those related rows. The problem is that there is no explicit relationship (like ID column that would clearly say which row is related to other row). Therefore I am trying to find relationship based on multiple conditions in WHERE clause.
The problem is that in few cases, the columns A and B could be NULL (for records where TYPE = 'M'). In such a cases I would like to ignore that condition, so It would use only first 3 conditions to determine relationship.
I have tried CASE Statement but is not working as expected:
SELECT [T1].[ID],[T1].[AlphaId],[T1].[Type],[T1].[A],[T1].[B],[T1].[Date],[T1].[ServiceID]
,( SELECT COUNT(*)
FROM MyTable T2
WHERE [T1].[AlphaId]=[T2].[AlphaId] AND
[T1].[Date]=[T2].[Date] AND
[T1].[ServiceID]=[T2].[ServiceID] AND
[T2].[A]=CASE WHEN [T2].[A] IS NULL THEN NULL ELSE [T1].[A] END AND
[T2].[B]=CASE WHEN [T2].[B] IS NULL THEN NULL ELSE [T1].[B] END AND
[T2].[Type]='M'
) as TotalCount
FROM MyTable T1
WHERE [T1].[Type] = 'E'
I can't ignore that condition, as for some cases the Date, ServiceID could be same, however it's the A, B which differs them. Luckily where A, B IS NULL, it is the Date, ServiceID which differs those two records.
http://sqlfiddle.com/#!3/c98db/1
Many thanks in advance.
You could join the tables and use COUNT and GROUP BY to get the counts. Then you can JOIN [A] and [B] if they are equal or NULL.
SELECT [T1].[ID],[T1].[AlphaId],[T1].[Type],[T1].[A],[T1].[B],[T1].[Date],[T1].[ServiceID], count([T2].[ID])
FROM MyTable T1
INNER JOIN MyTable T2 ON [T1].[AlphaId]=[T2].[AlphaId] AND
[T1].[Date]=[T2].[Date] AND
[T1].[ServiceID]=[T2].[ServiceID] AND
([T2].[A]= [T1].[A] OR [T2].[A] IS NULL )AND
([T2].[B]= [T1].[B] OR [T2].[B] IS NULL )AND
[T2].[Type] <> [T1].[Type]
WHERE [T1].[Type] = 'E'
GROUP BY [T1].[ID],[T1].[AlphaId],[T1].[Type],[T1].[A],[T1].[B],[T1].[Date],[T1].[ServiceID]

JOIN ON subselect returns what I want, but surrounding select is missing records when subselect returns NULL

I have a table where I am storing records with a Created_On date and a Last_Updated_On date. Each new record will be written with a Created_On, and each subsequent update writes a new row with the same Created_On, but an updated Last_Updated_On.
I am trying to design a query to return the newest row of each. What I have looks something like this:
SELECT
t1.[id] as id,
t1.[Store_Number] as storeNumber,
t1.[Date_Of_Inventory] as dateOfInventory,
t1.[Created_On] as createdOn,
t1.[Last_Updated_On] as lastUpdatedOn
FROM [UserData].[dbo].[StoreResponses] t1
JOIN (
SELECT
[Store_Number],
[Date_Of_Inventory],
MAX([Created_On]) co,
MAX([Last_Updated_On]) luo
FROM [UserData].[dbo].[StoreResponses]
GROUP BY [Store_Number],[Date_Of_Inventory]) t2
ON
t1.[Store_Number] = t2.[Store_Number]
AND t1.[Created_On] = t2.co
AND t1.[Last_Updated_On] = t2.luo
AND t1.[Date_Of_Inventory] = t2.[Date_Of_Inventory]
WHERE t1.[Store_Number] = 123
ORDER BY t1.[Created_On] ASC
The subselect works fine...I see X number of rows, grouped by Store_Number and Date_Of_Inventory, some of which have luo (Last_Updated_On) values of NULL. However, those rows in the sub-select where luo is null do not appear in the overall results. In other words, where I get 6 results in the sub-select, I only get 2 in the overall results, and its only those rows where the Last_Updated_On is not NULL.
So, as a test, I wrote the following:
SELECT 1 WHERE NULL = NULL
And got no results, but, when I run:
SELECT 1 WHERE 1 = 1
I get back a result of 1. Its as if SQL Server is not relating NULL to NULL.
How can I fix this? Why wouldn't two fields compare when both values are NULL?
You could use Coalesce (example assuming Store_Number is an integer)
ON
Coalesce(t1.[Store_Number],0) = Coalesce(t2.[Store_Number],0)
The ANSI Null comparison is not enabled by default; NULL doesn't equal NULL.
You can enable this (if your business case and your Database design usage of NULL requires this) by the Hint:
SET ansi_nulls off
Another alternative basic turn around using:
ON ((t1.[Store_Number] = t2.[Store_Number]) OR
(t1.[Store_Number] IS NULL AND t2.[Store_Number] IS NULL))
Executing your POC:
SET ansi_nulls off
SELECT 1 WHERE NULL = NULL
Returns:
1
This also works:
AND EXISTS (SELECT t1.Store_Number INTERSECT SELECT t2.Store_Number)

Assigning NULL value to column name using Case Statement of where is SQL Server 2008

I have a table GrowDaysLocation. In this table there can be two records with respect to DistrictId and RegionId
i.e;
RegionId=1 and DistrictId = NULL
RegionId=1 and DistrictId = 1
I have a condition that if the row doesn't exist for RegionId = 1 and DistrictId = 1 then get the row for RegionId = 1 and DistrictId = NULL.
How can I accomplish this using a single query?
The below is the query I have tried out.
In this query, I have used CASE in Where clause and Use sub-query to find out the row's existence but the problem is when I return NULL from the case it will not return any rows.
==================================================
SET ANSI_NULLS OFF
Select * From GrowDaysLocations
Where DistrictId =
( CASE WHEN (Select Count(*) From GrowDaysLocations
Where RegionId = '38D95A68-4A92-4D11-9A88-464CF1492880' AND DistrictId = 'F4B67A07-1BF7-42F5-9F19-77329A215D8B' AND
GrowDaysProfileId = '79F8BDBF-67D3-44A7-A790-1C10EE8B2AD0') > 0 THEN DistrictId
ELSE
NULL
END
)
AND RegionId = '38D95A68-4A92-4D11-9A88-464CF1492880' AND GrowDaysProfileId = '79F8BDBF-67D3-44A7-A790-1C10EE8B2AD0'
===========================================
The RANK function may give you the results you are looking for:
SELECT RegionId, DistrictId, GrowDaysProfileId
FROM
(SELECT RegionId
,DistrictId
,GrowDaysProfileId
,RANK() OVER(PARTITION BY RegionId, GrowDaysProfileId
ORDER BY DistrictId DESC) AS rankVal
From GrowDaysLocation) sub
WHERE rankVal = 1
This query will give you a result set with one row for each distinct RegionId and GrowDaysProfileId. If a RegionId/GrowDaysProfileId combination has more than one row in the table, the query will select a result based on the value of DistrictId. The row with the highest DistrictId value will be used first and the row with the lowest DistrictId (NULL being the lowest) last.
This is because when evaluating the condition
WHERE ColumnName = NULL
all rows are filtered out because when checking for equality, if any side is NULL, the row is immediately filtered out regardless of the condition (see Data Manipulation Language section) . You have to use
WHERE ColumnName IS NULL
In this case you can use
WHERE ISNULL(DistrictID, 'Empty') = ...
And use the 'Empty' string instead of null in the case statement.

Resources