0

我的查询有问题。我在这里有一个简单的例子来说明我拥有的代码。

SELECT distinct ID 
FROM Table  
WHERE IteamNumber in (132,434,675) AND Year(DateCreated) = 2019
      AND ID NOT IN (
                     SELECT Distinct ID FROM Table  
                     WHERE IteamNumber in (132,434,675) AND DateCreated < '2019-01-01')

如您所见,我正在检索 2019 年而不是更早创建的唯一数据 ID。

选择语句工作正常,但是一旦我使用 NOT IN 语句,查询可能会轻松超过 1 分钟。

我的另一个问题可能与运行 Microsoft Business Central 的 SQL Server 的计算机/服务器性能有关吗?因为即使使用 (NOT IN) 语句,同样的查询也能完美运行,但那是在 Microsoft 动态 C5 SQL Server 中。

所以我的问题是我的查询有问题还是主要是服务器问题?

更新:这是一个真实的例子:检索 500 行需要 25 秒

Select count(distinct b.No_),'2014'
from [Line] c    
inner join [Header] a
on a.CollectionNo = c.CollectionNo
Inner join [Customer] b
on b.No_ = a.CustomerNo

where  c.No_ in('2101','2102','2103','2104','2105')
and year(Enrollmentdate)= 2014 
and(a.Resignationdate < '1754-01-01 00:00:00.000' OR a.Resignationdate >= '2014-12-31')


and NOT EXISTS(Select distinct x.No_
                 from [Line] c    
                 inner join [Header] a
                 on a.CollectionNo = c.CollectionNo
                 Inner join [Customer] x
                 on x.No_ = a.CustomerNo
                 where x.No_ = b.No_ and 
                       c.No_ in('2101','2102','2103','2104','2105')
                       and Enrollmentdate < '2014-01-01'
                       and(a.Resignationdate < '1754-01-01 00:00:00.000' OR a.Resignationdate > '2014-12-31'))
4

3 回答 3

3

如果我理解正确,您可以将查询编写为GROUP BY带有HAVING子句的查询:

SELECT ID 
FROM t
WHERE IteamNumber in (132, 434, 675)
GROUP BY ID
HAVING MIN(DateCreated) >= '20190101' -- no row earlier than 2019
AND    MIN(DateCreated) <  '20200101' -- at least one row less than 2020

这将删除存在较早记录的行。您可以通过创建覆盖索引来进一步提高性能:

CREATE INDEX IX_t_0001 ON t (ID) INCLUDE (IteamNumber, DateCreated)
于 2019-08-09T07:54:27.237 回答
0

问题是由于您的IN陈述,我认为最好避免使用任何IN陈述而不是这个,join使用子查询创建并使用where子句过滤掉您的数据。

IN语句的情况下,您的表的每条记录都映射到子查询的所有记录,这肯定会减慢您的流程。

如果必须使用IN子句,则将其与index. 为您尊重的列创建适当的索引,从而提高您的性能。

而不是IN您可以使用EXISTS来提高您的查询的性能。

的例子EXISTS是:

SELECT distinct ID 
FROM Table AS T 
WHERE IteamNumber in (132,434,675) AND Year(DateCreated) = 2019
      AND NOT EXISTS (
                     SELECT Distinct ID FROM Table AS T2 
                     WHERE T1.ID=T2.ID 
                     AND IteamNumber in (132,434,675) AND DateCreated < '2019-01-01' )
于 2019-08-09T07:34:32.530 回答
0

我通常更喜欢JOINs而不是INs,你可以获得相同的结果,但引擎往往能够更好地优化它。

您将主查询 ( T1 ) 与 IN 子查询 ( T2 ) 连接起来,然后过滤T2.ID 为 null,确保您没有找到任何符合这些条件的记录。

SELECT distinct T1.ID 
FROM Table T1 
     LEFT JOIN Table T2 on T2.ID = T1.ID AND 
                     T2.IteamNumber in (132,434,675) AND T2.DateCreated < '2019-01-01'
WHERE T1.IteamNumber in (132,434,675) AND Year(T1.DateCreated) = 2019 AND
      T2.ID is null

更新:这是使用您的真实查询更新的提案。由于您的子查询具有内部连接,因此我创建了一个 CTE,因此您可以离开连接该子查询。功能是相同的,您将主查询与子查询连接起来,并且仅返回在子查询中找不到匹配记录的行。

with previous as (
  Select x.No_
  from [Line] c    
       inner join [Header] a on a.CollectionNo = c.CollectionNo
       inner join [Customer] x on x.No_ = a.CustomerNo
  where     c.No_ in ('2101','2102','2103','2104','2105')
        and Enrollmentdate < '2014-01-01'
        and (a.Resignationdate < '1754-01-01 00:00:00.000' OR a.Resignationdate > '2014-12-31'))
)
Select count(distinct b.No_),'2014'
from [Line] c    
     inner join [Header] a on a.CollectionNo = c.CollectionNo
     inner join [Customer] b on b.No_ = a.CustomerNo
     left join previous p on p.No_ = b.No_
where    c.No_ in ('2101','2102','2103','2104','2105')
     and year(Enrollmentdate)= 2014 
     and (a.Resignationdate < '1754-01-01 00:00:00.000' OR a.Resignationdate >= '2014-12-31')
     and p.No_ is null
于 2019-08-09T07:46:50.200 回答