简体   繁体   English

带“ not in”的SQL查询非常慢

[英]SQL query with “not in” is very slow

I have the following SQL query which is very slow. 我有下面的SQL查询,这是非常慢的。 How can I write the script differently? 如何编写不同的脚本?

select 
    pws_name 
from 
    pws_asset ass
join 
    Account acc on acc.AccountId = ass.pws_AccountId
where 
    acc.AccountNumber  in ('188012', '172146', '214727', '13636', '201194', '280294', '34328')
    and ass.pws_name not in ('1018684', '1018784', '1019584', '1019784', '1019884', '1070838', '1277139', '1277339'.........)

Kindly follow below steps, that will help in query performance. 请按照以下步骤操作,这将有助于提高查询性能。

Step 1: DECLARE two variables 步骤1:声明两个变量

DECLARE @AccNumList VARCHAR(4000)
DECLARE @PwsNameList VARCHAR(4000)

SET @AccNumList = '188012,172146,214727,13636,201194,280294,34328'
SET @PwsNameList = '1018684,1018784,1019584,1019784,1019884,1070838,1277139,1277339'

Step 2: Create two different temporary tables. 步骤2:创建两个不同的临时表。
1 for account numbers 1代表帐号

Create table #tblAcNum(AccountNumber VARCHAR(50))

2 for pws_name not needed 2不需要pws_name

Create table #tblPwsNameNotNeeded(pws_name VARCHAR(50))

Step 3: Add records in above two tables which are used in IN and NOT IN. 步骤3:将记录添加到上面两个表中,分别用于IN和NOT IN。
Please check this Split csv string using XML in SQL Server for reference. 在SQL Server中使用XML检查此Split csv字符串,以供参考。

INSERT INTO #tblAcNum(AccountNumber)
SELECT
l.value('.','VARCHAR(50)') AcNum
FROM
(
SELECT CAST('<a>' + REPLACE(@AccNumList,',','</a><a>') + '</a>' AS XML) AcNumXML
) x
CROSS APPLY x.AcNumXML.nodes('a') Split(l)

INSERT INTO #tblPwsNameNotNeeded(pws_name)
SELECT
l.value('.','VARCHAR(50)') pws_name
FROM
(
SELECT CAST('<a>' + REPLACE(@PwsNameList,',','</a><a>') + '</a>' AS XML) PwsNameXML
) x
CROSS APPLY x.PwsNameXML.nodes('a') Split(l)

Step 3: INNER JOIN #tblAcNum table with account table with accountnumber column 步骤3:INNER JOIN #tblAcNum表和带有accountnumber列的客户表

Step 4: Use NOT EXISTS() function for pws_name not needed like below 步骤4:对不需要的pws_name使用NOT EXISTS()函数,如下所示

WHERE NOT EXISTS
(
SELECT 1
FROM #tblPwsNameNotNeeded pn
Where pn.pws_name = ass.pws_name
)

Step 5: Drop temporary tables after your select query. 步骤5:在选择查询后删除临时表。

DROP TABLE tblAcNum;
DROP TABLE #tblPwsNameNotNeeded;

Please check below query. 请检查以下查询。

DECLARE @AccNumList VARCHAR(4000)
DECLARE @PwsNameList VARCHAR(4000)

SET @AccNumList = '188012,172146,214727,13636,201194,280294,34328'
SET @PwsNameList = '1018684,1018784,1019584,1019784,1019884,1070838,1277139,1277339'

Create table #tblAcNum(AccountNumber VARCHAR(50))

Create table #tblPwsNameNotNeeded(pws_name VARCHAR(50))

INSERT INTO #tblAcNum(AccountNumber)
SELECT
l.value('.','VARCHAR(50)') AcNum
FROM
(
SELECT CAST('<a>' + REPLACE(@AccNumList,',','</a><a>') + '</a>' AS XML) AcNumXML
) x
CROSS APPLY x.AcNumXML.nodes('a') Split(l)

INSERT INTO #tblPwsNameNotNeeded(pws_name)
SELECT
l.value('.','VARCHAR(50)') pws_name
FROM
(
SELECT CAST('<a>' + REPLACE(@PwsNameList,',','</a><a>') + '</a>' AS XML) PwsNameXML
) x
CROSS APPLY x.PwsNameXML.nodes('a') Split(l)

select 
ass.pws_name 
from pws_asset ass 
join Account acc on acc.AccountId = ass.pws_AccountId 
INNER JOIN #tblAcNum an ON an.AccountNumber = acc.AccountNumber
WHERE NOT EXISTS
(
SELECT 1
FROM #tblPwsNameNotNeeded pn
Where pn.pws_name = ass.pws_name
)

DROP TABLE tblAcNum;
DROP TABLE #tblPwsNameNotNeeded;

Try this: 尝试这个:

; with cte_excludepws as
(select AccountId from pws_asset where pws_name not in ('1018684', '1018784', '1019584', '1019784', '1019884', '1070838', '1277139', '1277339'.........))
select 
    pws_name 
from 
    pws_asset ass
join 
    Account acc on acc.AccountId = ass.pws_AccountId
where ass.AccountId not in (select AccountId from cte_excludepws)
and acc.AccountNumber  in ('188012', '172146', '214727', '13636', '201194', '280294', '34328')

Alternatively if you can - take the AccountID's into a temporary table instead of cte and create an index on it. 或者,如果可以的话-将AccountID而不是cte放入临时表中并在其上创建索引。

First, be sure that the account numbers are really strings. 首先可以肯定的是, 账号是真的字符串。 If they are numbers, drop the single quotes! 如果它们是数字,请删除单引号!

Then, for this query 然后,对于此查询

select a.pws_name 
from pws_asset a join 
     Account ac 
     on ac.AccountId = a.pws_AccountId
where ac.AccountNumber  in ('188012', '172146', '214727', '13636', '201194', '280294', '34328') and
      a.pws_name not in ('1018684', '1018784', '1019584', '1019784', '1019884', '1070838', '1277139', '1277339'.........);

I would recommend indexes on: account(accountNumber, AccountId) and pws_asset(pws_AccountId, pws_name) . 我会建议以下索引: account(accountNumber, AccountId)pws_asset(pws_AccountId, pws_name)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM