Finding Not null on multiple columns using COALESCE - sql

I have a query to find not null on 2 columns on a table which is a view , hence it is taking a lot of time for execution.
The query is : Query1
SELECT [Table1].M, [[Table1]].B, [Table1].P
FROM [Table1]
WHERE ((([[Table1]].B) Is Not Null) AND (([[Table1]].P) Is Not Null));
Does the below query does the same function as Query1 with faster execution time ?
SELECT [Table1].M, [[Table1]].B, [Table1].P
FROM [Table1]
WHERE COALESCE (([[Table1]].B),([[Table1]].P)) Is Not Null
Any help would be of great help and thanks in advance.
The view query
select dbo.TABLE1.[COL1]
, dbo.TABLE1.[COL2]
, RIGHT(dbo.TABLE1.M, 12) as M
, dbo.TABLE2.[MD]
, dbo.TABLE1.[COL3]
, dbo.TABLE1.[COL4]
, dbo.TABLE3.COL1
, dbo.TABLE3.[COL2]
, dbo.TABLE3.[COL3]
, dbo.TABLE4.[COL1]
, dbo.TABLE5.[COL1]
, dbo.TABLE6.[COL1]
, dbo.TABLE7.[COL1] as [BA]
, dbo.TABLE8.[COL1]
, dbo.TABLE3.[COL4]
, dbo.TABLE3.[COL5]
, dbo.TABLE3.[COL6]
from dbo.TABLE1
left outer join dbo.TABLE2
on dbo.TABLE1.M = dbo.TABLE2.M
left outer join dbo.TABLE3
on dbo.TABLE1.M = dbo.TABLE3.M
left outer join dbo.TABLE5
on dbo.TABLE3.[OBJ_NR] = dbo.TABLE5.OBJ
left outer join dbo.TABLE6
on dbo.TABLE3.[OBJ_NR] = dbo.TABLE6.OBJ
left outer join dbo.TABLE7
on dbo.TABLE3.[OBJ_NR] = dbo.TABLE7.OBJ
left outer join dbo.TABLE4
on dbo.TABLE3.[OBJ_NR] = dbo.TABLE4.OBJ
left outer join dbo.TABLE8
on dbo.TABLE3.[OBJ_NR] = dbo.TABLE8.OBJ
where (
(
dbo.TABLE1.[COL1] not in (
'XX'
, 'YY'
)
)
and (dbo.TABLE1.COL5 = 'x')
)

No, both queries aren't equivalent.
The WHERE clause in the second one is equivalent to
WHERE [[Table1]].B Is Not Null OR [[Table1]].P Is Not Null
COALESCE will evaluate the first parameter and return it if not null. Otherwise, it will return the second one if not null, and so on, until reaching the last parameter, which will be returned whatever its value. So COALESCE(...) IS NOT NULL needs only one not null value to return true, not all.

I've tried this out on a table in my development DB. Here are the results:
with only PK index: 2 minutes for 4 million selected records out of 8 million table
with index on 3 selected columns (none of them PK) 1.8 seconds.
You might need to do some testing to get the right indexes for your setup but here is the sample of what i changed:
select [col1]
, [col2]
, [col3]
from [dbo].[tbl]
where col2 is not null
and col3 is not null
create nonclustered index [idx_test] on [dbo].[tbl] (
[col2] asc
, [col3] asc
) INCLUDE ([col1])

Related

Need to optimise select query

I have a query that does a select with joins from multiple tables that contains in total about 90 million rows. I only need data from the last 30 days. The problem is that when I run the select query the sql server throws a timeout while the query is running and new records are not created during this time frame. This query takes about 5 seconds to complete.
I would like to optimise this query so that it wont go through the entire tables looking at the datetime and would only search from the latest entries.
Right now it seems that I would need to index datetime column. Please advise if I need to create indexes or if there is another way to optimise this query.
SELECT [table1].Column1 AS InvoiceNo,
'ND' AS VATRegistrationNumber,
'ND' AS RegistrationNumber,
Column2 AS Country,
[table2].Column3 + ' ' + [table2].Column4 AS Name,
CAST([table1].Column5 AS date) AS InvoiceDate,
'SF' AS InvoiceType,
'' AS SpecialTaxation,
'' AS VATPointDate,
ROUND([table1Line].Column6, 2) AS TaxableValue,
CASE
WHEN [table1Line].Column7 = 9 THEN 'PVM2'
WHEN [table1Line].Column7 = 21 THEN 'PVM1'
WHEN [table1Line].Column7 = 0 THEN 'PVM14'
END AS TaxCode,
CAST([table1Line].Column7 AS int) AS TaxPercentage,
table1Line.Column8 - ROUND([table1Line].Column6, 2) AS Amount,
'' AS VATPointDate2,
[table1].Column1 AS InvoiceNo,
'' AS ReferenceNo,
'' AS ReferenceDate,
[table1].CustomerPersonID AS CustomerID
FROM [table1]
INNER JOIN [table2] ON [table1].CustomerPersonID = [table2].ID
INNER JOIN [table3] ON [table2].Column9 = [table3].ID
INNER JOIN [table1Line] ON [table1].ID = [table1Line].table1ID
INNER JOIN [table4] ON table1Line.TaxID = Tax.ID
INNER JOIN [table5] ON [table1].CompanyID = Company.ID
INNER JOIN table6 ON [table1].SalesChannelID = table6.ID
WHERE Column5 LIKE '%date%'
AND table6.id = 5
OR table6.id = 2
AND Column5 LIKE '%date%'
ORDER BY Column5 DESC;
First things first, each database runs a little differently because the optimizer has been running and figuring out how the unique circumstances can be improved and continuously tries to make common things run better.
There's also versioning differences that also play a part is the performance of the server.
Besides that stuff, Here's a few things to do to optimize this query.
When working with Joins, Your Joined table comes first then compare against the already specified table.
For example t2 checks against t1:
select t1.name, t2.car
from customers as t1
left join purchases as t2
on t2.customerid = t1.customerid
The next thing I see is the Like condition in the Where part of the code.
The stored date that it's finding is stored as text in your example.
I would recommend processing the date as a datetime instead of a string type of datatype.
I would include that in the code below, but I'm not sure what the format looks like for your string of text.
%date% is the same thing as saying "Contains date".
This takes the date string, and tries to see if it matches in every position of characters from left to right.
So if your date text is 20200130, it will check to see if it matches 2date0200130, then tries 20date200130, then tries 202date00130, etc.
It will significantly increase the time it takes to process.
I also see that the date is being searched accidently two times instead of one.
I would recommend doing:
WHERE LTRIM(RTRIM(Column5)) LIKE 'date'
As for the Inner Joins, I would not use them.
Use the Left join, and then in the Where, I would make sure it had no Null values for that joined data.
This makes the Left Join work the same as the Inner Join and runs more optimally when you are running the query.
For Instance, the first Join would look like this:
FROM [table1]
LEFT JOIN [table2] ON [table2].ID = [table1].CustomerPersonID
WHERE table2.id IS NOT NULL
I see an error in the code in the Where statement:
AND table6.id = 5
OR tables6.id = 2
This should be:
AND (tables6.id = 5 OR tables6.id = 2)
So here should be an optimized version of your code:
SELECT [table1].Column1 AS InvoiceNo,
'ND' AS VATRegistrationNumber,
'ND' AS RegistrationNumber,
Column2 AS Country,
[table2].Column3 + ' ' + [table2].Column4 AS Name,
CAST([table1].Column5 AS date) AS InvoiceDate,
'SF' AS InvoiceType,
'' AS SpecialTaxation,
'' AS VATPointDate,
ROUND([table1Line].Column6, 2) AS TaxableValue,
(CASE WHEN [table1Line].Column7 = 9 THEN 'PVM2'
WHEN [table1Line].Column7 = 21 THEN 'PVM1'
WHEN [table1Line].Column7 = 0 THEN 'PVM14'
ELSE '' END ) AS TaxCode,
CAST([table1Line].Column7 AS int) AS TaxPercentage,
table1Line.Column8 - ROUND([table1Line].Column6, 2) AS Amount,
'' AS VATPointDate2,
[table1].Column1 AS InvoiceNo,
'' AS ReferenceNo,
'' AS ReferenceDate,
[table1].CustomerPersonID AS CustomerID
FROM [table1]
LEFT JOIN [table2] ON [table2].ID = [table1].CustomerPersonID
LEFT JOIN [table3] ON [table3].ID = [table2].Column9
LEFT JOIN [table1Line] ON [table1Line].table1ID = [table1].ID
LEFT JOIN [table4] ON [table4].ID = table1Line.TaxID
LEFT JOIN [table5] ON [table5].ID = [table1].CompanyID
LEFT JOIN [table6] ON table6.ID = [table1].SalesChannelID
WHERE table2.ID IS NOT null
AND table3.ID IS NOT null
AND table1Line.ID IS NOT null
AND table4.ID IS NOT null
AND table5.ID IS NOT null
AND table6.ID IS NOT null
AND LTRIM(RTRIM(Column5)) LIKE 'date'
AND (table6.id = 5 OR table6.id = 2)
ORDER BY Column5 DESC;

Join 2 tables with match of 2 columns from two tables

I have 2 tables :
TransferPointType
--------------------------------------------------
[Player(int)] [ID(int)] [Type(tinyint)] [Level(int)] [Before(money)] [Now(money)] [After(money)]
X
X
X
[Transfer]
--------------------------------------------------
[Player(int)] [ID(int)] [Type(tinyint)] [Amount(money)] [Created(datetime)] [Description(nvarchar256)]
The resulting table should look like this
[Player] [ID] [Level] [Before] [Now] [After] [Created] [Description]
--[Transfer] = TransferPointType--
and conditions
match between TransferPointType.player=[Transfer].player, TransferPointType.ID=[Transfer].ID
according to this match add others columns [Type] [Level] [Before] [Now] [After] from TransferPointType
and columns - [Created] [Description] from [Transfer]
-----------------------------------------------------------------------
where player=1111 and ID IN (1111,xxxx,xxx,xx,xx,xxx)
I think about the left join or union but I am not able to write a reasonable JOIN. If I tried UNION where i optimalized number of columns, I got to the point where the sql server show an error: Arithmetic overflow error -datetime. So, I tried to convert it with (example) select CONVERT(datetime, cast(20140806 as char(8)) ) without success either.
Maybe I'm thinking complicatedly and it could be written by simply select ...
Try this:
select a.type, a.level, a.before, a.now, a.after, b.created, b.description
from TransferPointType a
join Transfer b on a.player = b.player and a.ID = b.ID
where a.player = 1111
and a.ID IN (1111,xxxx,xxx,xx,xx,xxx);
If you expect TransferPointType has ID's that are not in Transfer table, then add "left" in front of join statement.

How to get data where the whole column is NOT NULL?

I am trying to pull data where a specific column is completely not null. It should only return the data if ALL of the rows in the column meet that requirement. Doing simply IS NOT NULL will not work. In short, I am trying to find contracts where all of the products on that contract has been terminated and to only return that data.
Here is what I have so far, its barebone:
SELECT
T0.CustomerCode
, T0.CustomerName
, T1.ContractID
, T1.StartDate
, T1.TerminationDate
, T2.ProductRecordID
, T2.ProductSN
, T2.CompanySN
, T2.ProductRecordStatus
FROM
T0
INNER JOIN T1 ON T0.ContractID = T1.ContractID
INNER JOIN T2 ON T1.ProductRecordID = T2.ProductRecordID
WHERE T0.ProductRecordStatus = 'A'
A solution can be to count null value in the specified column and check if this number is equal to zero.
DECLARE #nullCount int = 1;
SELECT
#nullCount = COUNT(1)
FROM
[your_table]
WHERE
[your_column] IS NULL;
IF #nullCount = 0
SELECT
T0.CustomerCode , T0.CustomerName , T1.ContractID , T1.StartDate , T1.TerminationDate ,
T2.ProductRecordID , T2.ProductSN , T2.CompanySN , T2.ProductRecordStatus
FROM T0
INNER JOIN T1 ON T0.ContractID = T1.ContractID INNER JOIN T2 ON T1.ProductRecordID =
T2.ProductRecordID
WHERE T0.ProductRecordStatus = 'A';
in this way if you have one or more null values the query is not even performed.

Performance tuning of query

I have a query which takes a long time to run. It is probably because I used too many isnulls in the join condition. How can I optimise it by removing the isnull?
Is there any alternate way without updating the table? The query is given below:
select pos.C_id
,pos.s_id
,pos.A_id
,pos.Ad_id
,pos.Pr_id
,pos.prog_id
,pos.port_id
,pos.o_type
,pos.o_id
,pos.s_id
,pos.c_id
,pos.s_type_id
,pos.s_type
,pos.e_date
,pos.mv
,0 is_pub
, 1 is_adj
,pos.is_unsup
,getdate() date
,getdate() timestamp
from #temp pos
left join acc c with(nolock) ON pos._id = c.c_id
AND pos.account_id = c.account_id
AND isnull(pos.Pr_id,0) = isnull(c.pr_id,0)
AND isnull(pos.prog_id,0) = isnull(c.prog_id,0)
AND isnull(pos.port_id,0) = isnull(c.port_id,0)
and isnull(pos.style_type_id,0)=isnull(c.s_type_id,0)
AND pos.s_id = c._id
AND pos.c_id = c.c_id
AND pos.s_type = c.s_type
AND pos.is_unsup = c.is_uns
AND pos.is_pub = 1
where c.a_id is null
What about the query below
select pos.C_id
,pos.s_id
,pos.A_id
,pos.Ad_id
,pos.Pr_id
,pos.prog_id
,pos.port_id
,pos.o_type
,pos.o_id
,pos.s_id
,pos.c_id
,pos.s_type_id
,pos.s_type
,pos.e_date
,pos.mv
,0 is_pub
, 1 is_adj
,pos.is_unsup
,getdate() date
,getdate() timestamp
from #temp pos
left join acc c with(nolock) ON pos._id = c.c_id
AND pos.account_id = c.account_id
AND pos.Pr_id = c.pr_id
AND pos.prog_id = c.prog_id
AND pos.port_id = c.port_id
and pos.style_type_id=c.s_type_id
AND pos.s_id = c._id
AND pos.c_id = c.c_id
AND pos.s_type = c.s_type
AND pos.is_unsup = c.is_uns
AND pos.is_pub = 1
where c.a_id is null
union all
select pos.C_id
,pos.s_id
,pos.A_id
,pos.Ad_id
,pos.Pr_id
,pos.prog_id
,pos.port_id
,pos.o_type
,pos.o_id
,pos.s_id
,pos.c_id
,pos.s_type_id
,pos.s_type
,pos.e_date
,pos.mv
,0 is_pub
, 1 is_adj
,pos.is_unsup
,getdate() date
,getdate() timestamp
from #temp pos
left join acc c with(nolock) ON pos._id = c.c_id
AND pos.account_id = c.account_id
AND pos.s_id = c._id
AND pos.c_id = c.c_id
AND pos.s_type = c.s_type
AND pos.is_unsup = c.is_uns
AND pos.is_pub = 1
where c.a_id is null
AND pos.Pr_id is null AND c.pr_id is null
AND pos.prog_id is null AND c.prog_id is null
AND pos.port_id is null AND c.port_id is null
and pos.style_type_id is null AND c.s_type_id is null
try using
AND (pos.Pr_id = c.pr_id OR (pos.Pr_id IS NULL AND c.pr_id IS NULL))
instead of
AND ISNULL(pos.Pr_id,0) = ISNULL(c.pr_id,0)
IS NULL is more efficient than ISNULL
You really need to set a clustered index on your temp table #temp, if not present sql-server will provide a default hash-based index for joins, and it is not performant for large tables.
If any of all that id's columns you have in your #temp table is a unique key you really need to create a clustered index on it:
CREATE CLUSTERED INDEX cx_temp ON #temp (YourIDColumn);
If you have not a key column in #temp add an identity primary key to it in this way:
1) if you use SELECT INTO approach to create #temp, change
select *
into #temp
from YourQuery
in
select IDENTITY (int, 1,1) ThisIsTheKey, *
into #temp
from YourQuery
-- and then add the index
CREATE CLUSTERED INDEX cx_temp ON #temp (ThisIsTheKey);
1) if you use CREATE TABLE + INSERT INTO approach, simply add the column like this:
CREATE TABLE #TEMP (
ThisIsTheKey INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
..
..
-- ALL YOUR OTHER COLUMNS
..
..
)
Don't rely on covering non clustered indexes because the optimizer will likely not use them because you are selecting too many columns.
First test with the clustered index, then if you need further optimization you can try to add some specific non clustered index.

How to improve sql script performance

The following script is very slow when its run.
I have no idea how to improve the performance of the script.
Even with a view takes more than quite a lot minutes.
Any idea please share to me.
SELECT DISTINCT
( id )
FROM ( SELECT DISTINCT
ct.id AS id
FROM [Customer].[dbo].[Contact] ct
LEFT JOIN [Customer].[dbo].[Customer_ids] hnci ON ct.id = hnci.contact_id
WHERE hnci.customer_id IN (
SELECT DISTINCT
( [Customer_ID] )
FROM [Transactions].[dbo].[Transaction_Header]
WHERE actual_transaction_date > '20120218' )
UNION
SELECT DISTINCT
contact_id AS id
FROM [Customer].[dbo].[Restaurant_Attendance]
WHERE ( created > '2012-02-18 00:00:00.000'
OR modified > '2012-02-18 00:00:00.000'
)
AND ( [Fifth_Floor_London] = 1
OR [Fourth_Floor_Leeds] = 1
OR [Second_Floor_Bristol] = 1
)
UNION
SELECT DISTINCT
( ct.id )
FROM [Customer].[dbo].[Contact] ct
INNER JOIN [Customer].[dbo].[Wifinity_Devices] wfd ON ct.wifinity_uniqueID = wfd.[CustomerUniqueID]
AND startconnection > '2012-02-17'
UNION
SELECT DISTINCT
comdt.id AS id
FROM [Customer].[dbo].[Complete_dataset] comdt
LEFT JOIN [Customer].[dbo].[Aggregate_Spend_Counts] agsc ON comdt.id = agsc.contact_id
WHERE agsc.contact_id IS NULL
AND ( opt_out_Mail <> 1
OR opt_out_email <> 1
OR opt_out_SMS <> 1
OR opt_out_Mail IS NULL
OR opt_out_email IS NULL
OR opt_out_SMS IS NULL
)
AND ( address_1 IS NOT NULL
OR email IS NOT NULL
OR mobile IS NOT NULL
)
UNION
SELECT DISTINCT
( contact_id ) AS id
FROM [Customer].[dbo].[VIP_Card_Holders]
WHERE VIP_Card_number IS NOT NULL
) AS tbl
Wow, where to start...
--this distinct does nothing. Union is already distinct
--SELECT DISTINCT
-- ( id )
--FROM (
SELECT DISTINCT [Customer_ID] as ID
FROM [Transactions].[dbo].[Transaction_Header]
where actual_transaction_date > '20120218' )
UNION
SELECT
contact_id AS id
FROM [Customer].[dbo].[Restaurant_Attendance]
-- not sure that you are getting the date range you want. Should these be >=
-- if you want everything that occurred on the 18th or after you want >= '2012-02-18 00:00:00.000'
-- if you want everything that occurred on the 19th or after you want >= '2012-02-19 00:00:00.000'
-- the way you have it now, you will get everything on the 18th unless it happened exactly at midnight
WHERE ( created > '2012-02-18 00:00:00.000'
OR modified > '2012-02-18 00:00:00.000'
)
AND ( [Fifth_Floor_London] = 1
OR [Fourth_Floor_Leeds] = 1
OR [Second_Floor_Bristol] = 1
)
-- all of this does nothing because we already have every id in the contact table from the first query
-- UNION
-- SELECT
-- ( ct.id )
-- FROM [Customer].[dbo].[Contact] ct
-- INNER JOIN [Customer].[dbo].[Wifinity_Devices] wfd ON ct.wifinity_uniqueID = wfd.[CustomerUniqueID]
-- AND startconnection > '2012-02-17'
UNION
-- cleaned this up with isnull function and coalesce
SELECT
comdt.id AS id
FROM [Customer].[dbo].[Complete_dataset] comdt
LEFT JOIN [Customer].[dbo].[Aggregate_Spend_Counts] agsc ON comdt.id = agsc.contact_id
WHERE agsc.contact_id IS NULL
AND ( isnull(opt_out_Mail,0) <> 1
OR isnull(opt_out_email,0) <> 1
OR isnull(opt_out_SMS,0) <> 1
)
AND coalesce(address_1 , email, mobile) IS NOT NULL
UNION
SELECT
( contact_id ) AS id
FROM [Customer].[dbo].[VIP_Card_Holders]
WHERE VIP_Card_number IS NOT NULL
-- ) AS tbl
Where exists is generally faster than in as well.
Or conditions are generally slower as well, use more union statements instead.
And learn to use left joins correctly. If you have a where condition (other than where id is null) on the table on teh right side of a left join, it will convert to an inner join. If this is not what you want, then your code is currently giving you an incorrect result set.
See http://wiki.lessthandot.com/index.php/WHERE_conditions_on_a_LEFT_JOIN for an explanation of how to fix.
As stated in a comment optimize one at a time. See which one takes the longest and focus on that one.
union will remove duplicates so you don't need the distinct on the individual queries
On you first I would try this:
The left join is killed by the WHERE hnci.customer_id IN so you might as well have a join.
The sub-query is not efficient as cannot use an index on the IN.
The query optimizer does not know what in ( select .. ) will return so it cannot optimize use of indexes.
SELECT ct.id AS id
FROM [Customer].[dbo].[Contact] ct
JOIN [Customer].[dbo].[Customer_ids] hnci
ON ct.id = hnci.contact_id
JOIN [Transactions].[dbo].[Transaction_Header] th
on hnci.customer_id = th.[Customer_ID]
and th.actual_transaction_date > '20120218'
On that second join the query optimizer has the opportunity of which condition to apply first. Let say [Customer].[dbo].[Customer_ids].[customer_id] and [Transactions].[dbo].[Transaction_Header] each have indexes. The query optimizer has the option to apply that before [Transactions].[dbo].[Transaction_Header].[actual_transaction_date].
If [actual_transaction_date] is not indexed then for sure it would do the other ID join first.
With your in ( select ... ) the query optimizer has no option but to apply the actual_transaction_date > '20120218' first. OK some times query optimizer is smart enough to use an index inside the in outside the in but why make it hard for the query optimizer. I have found the query optimizer make better decisions if you make the decisions easier.
A join on a sub-query has the same problem. You take options away from the query optimizer. Give the query optimizer room to breathe.
try this, temptable should help you:
IF OBJECT_ID('Tempdb..#Temp1') IS NOT NULL
DROP TABLE #Temp1
--Low perfomance because of using "WHERE hnci.customer_id IN ( .... ) " - loop join must be
--and this "where" condition will apply to two tables after left join,
--so result will be same as with two inner joints but with bad perfomance
--SELECT DISTINCT
-- ct.id AS id
--INTO #temp1
--FROM [Customer].[dbo].[Contact] ct
-- LEFT JOIN [Customer].[dbo].[Customer_ids] hnci ON ct.id = hnci.contact_id
--WHERE hnci.customer_id IN (
-- SELECT DISTINCT
-- ( [Customer_ID] )
-- FROM [Transactions].[dbo].[Transaction_Header]
-- WHERE actual_transaction_date > '20120218' )
--------------------------------------------------------------------------------
--this will give the same result but with better perfomance then previouse one
--------------------------------------------------------------------------------
SELECT DISTINCT
ct.id AS id
INTO #temp1
FROM [Customer].[dbo].[Contact] ct
JOIN [Customer].[dbo].[Customer_ids] hnci ON ct.id = hnci.contact_id
JOIN ( SELECT DISTINCT
( [Customer_ID] )
FROM [Transactions].[dbo].[Transaction_Header]
WHERE actual_transaction_date > '20120218'
) T ON hnci.customer_id = T.[Customer_ID]
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
INSERT INTO #temp1
( id
)
SELECT DISTINCT
contact_id AS id
FROM [Customer].[dbo].[Restaurant_Attendance]
WHERE ( created > '2012-02-18 00:00:00.000'
OR modified > '2012-02-18 00:00:00.000'
)
AND ( [Fifth_Floor_London] = 1
OR [Fourth_Floor_Leeds] = 1
OR [Second_Floor_Bristol] = 1
)
INSERT INTO #temp1
( id
)
SELECT DISTINCT
( ct.id )
FROM [Customer].[dbo].[Contact] ct
INNER JOIN [Customer].[dbo].[Wifinity_Devices] wfd ON ct.wifinity_uniqueID = wfd.[CustomerUniqueID]
AND startconnection > '2012-02-17'
INSERT INTO #temp1
( id
)
SELECT DISTINCT
comdt.id AS id
FROM [Customer].[dbo].[Complete_dataset] comdt
LEFT JOIN [Customer].[dbo].[Aggregate_Spend_Counts] agsc ON comdt.id = agsc.contact_id
WHERE agsc.contact_id IS NULL
AND ( opt_out_Mail <> 1
OR opt_out_email <> 1
OR opt_out_SMS <> 1
OR opt_out_Mail IS NULL
OR opt_out_email IS NULL
OR opt_out_SMS IS NULL
)
AND ( address_1 IS NOT NULL
OR email IS NOT NULL
OR mobile IS NOT NULL
)
INSERT INTO #temp1
( id
)
SELECT DISTINCT
( contact_id ) AS id
FROM [Customer].[dbo].[VIP_Card_Holders]
WHERE VIP_Card_number IS NOT NULL
SELECT DISTINCT
id
FROM #temp1 AS T