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

时间:2019-09-09 05:25:00

标签: sql sql-server tsql query-performance

我有以下非常慢的SQL查询。我该如何写不同的脚本?

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

3 个答案:

答案 0 :(得分:1)

请按照以下步骤操作,这将有助于提高查询性能。

步骤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'

第2步:创建两个不同的临时表。
1个代表帐号

Create table #tblAcNum(AccountNumber VARCHAR(50))

不需要2个pws_name

Create table #tblPwsNameNotNeeded(pws_name VARCHAR(50))

第3步:在上面两个表中添加记录,分别用于IN和NOT IN。
请检查此Split csv string using XML in SQL Server以供参考。

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)

第3步:INNER JOIN #tblAcNum表与带有accountnumber列的account表

第4步:对不需要的pws_name使用NOT EXISTS()函数,如下所示

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

第5步:在选择查询后删除临时表。

DROP TABLE tblAcNum;
DROP TABLE #tblPwsNameNotNeeded;

请检查以下查询。

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;

答案 1 :(得分:0)

尝试一下:

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

或者,如果可以的话-将AccountID替换为临时表而不是cte并在其上创建索引。

答案 2 :(得分:0)

首先,请确保帐户数字确实是字符串。如果它们是数字,请删除单引号!

然后,针对此查询

const ids = [
{
  "id": "27675548",
  "identifier.id": "156473847",
  "address": "Rua Brasilia, 23232, Sao Benedito - BH"
},
{
  "id": "27675569",
  "identifier.id": "156473847",
  "address": "Rua Brasilia, 11, Sao Benedito - BH"
}];

const result = Object.values(ids.reduce((acc, item) => {
  const identifier = item["identifier.id"];
  if(!acc[identifier]) acc[identifier] = { "identifier.id": identifier, "registrations": []};
  acc[identifier].registrations.push({id: item.id, address: item.address});
  return acc;
}, {}));

console.log(result);

我建议在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'.........); account(accountNumber, AccountId)上建立索引。