Sql server 更好的tsql查询,以确定谁是新客户(或替代不存在的客户)

Sql server 更好的tsql查询,以确定谁是新客户(或替代不存在的客户),sql-server,tsql,query-optimization,in-subquery,Sql Server,Tsql,Query Optimization,In Subquery,我有一张桌子,上面有我们所有的订单。订单链接到一个人。每个人都是公司的员工。现在我需要一份在某个日期之前从未订购过的所有公司的名单。查询工作正常,但速度非常慢 这是我的T-SQL查询: SELECT DISTINCT p1.company_id FROM order o JOIN person p1 ON (o.person_id = p1.id AND p1.company_id IS NOT NULL) WHERE o.orderDate > '2017

我有一张桌子,上面有我们所有的订单。订单链接到一个人。每个人都是公司的员工。现在我需要一份在某个日期之前从未订购过的所有公司的名单。查询工作正常,但速度非常慢

这是我的T-SQL查询:

SELECT
    DISTINCT p1.company_id
FROM
    order o
    JOIN person p1 ON (o.person_id = p1.id AND p1.company_id IS NOT NULL)
WHERE
    o.orderDate > '2017-01-01'
AND
    o.orderDate < '2017-09-01'
AND NOT EXISTS (SELECT
                    p2.company_id
                FROM
                    order o2
                    JOIN person p2 ON (o2.person_id = p2.id AND p2.company_id = p1.company_id)
                WHERE
                    o2.orderDate < '2017-01-01')
我已经把它从不存在改成不存在。因为这是这里大多数人推荐的。没什么帮助。更好的索引稍微改善了这种情况,但查询仍然很慢。我认为这是因为对于每个订单,它都必须执行子查询

这是执行计划: 为了简单起见,我删除了上面示例中的一些WHERE子句

查询在Azure SQL和SQL Server Express 12上运行以进行开发


有谁对如何解决这个问题有更好的想法吗?

我想这样就行了,哎哟,我没有订购

;With FirstOrders
as
(
    Select p1.company_id   
    ,      MIN(o.orderDate) as FirstCompanyOrder
    From Orders o 
    Join Person P1 on o.person_id = p1.id
    Group by P1.Company_id
    Having MIN(o.OrderDate) < '2017-01-01'
)

Select distinct o.company_id
From      Orders      o 
Left join FirstOrders FO on o.Company_id = FO.ComapnyId
where FO.company_id is null

如果你有执行计划要分享,它将有助于绩效分析

我对查询做了一些更改,如下所示,您可以尝试改进它

SELECT p1.company_id
FROM  order o
INNER JOIN person p1 
    ON (o.person_id = p1.id AND p1.company_id IS NOT NULL)
GROUP BY p1.company_id
HAVING SUM(CASE WHEN  (o.orderDate > '2017-01-01' AND  o.orderDate < '2017-09-01') THEN 1 ELSE 0 END) > 0
      AND
      SUM(CASE WHEN  orderDate < '2017-01-01' THEN 1 ELSE 0 END) = 0

这个怎么样。希望我正确理解了任务

(
  SELECT p1.company_id
  FROM order o
  JOIN person p1 
    ON o.person_id = p1.id 
  WHERE p1.company_id IS NOT NULL
    AND o.orderDate > '2017-01-01'
    AND o.orderDate < '2017-09-01'
)
EXCEPT
(
  SELECT p2.company_id
  FROM order o2
  JOIN person p2 
    ON o2.person_id = p2.id 
  WHERE p2.company_id IS NOT NULL
    AND o2.orderDate < '2017-01-01'
)

也许这会帮助你:

WITH cte AS
(
    SELECT o.person_id, MIN(o.orderDate) minOrderDate
        FROM order o 
        GROUP BY o.person_id
)
SELECT DISTINCT p1.company_id
    FROM person p1
    JOIN cte ON cte.person_id = p1.id
    WHERE p1.company_id IS NOT NULL AND cte.minOrderDate > '2017-01-01' AND cte.minOrderDate < '2017-09-01';

寻求性能帮助的问题应包括相关表格的DDL、DML以及测试数据。如果您的测试数据很大,尝试为表编写架构和统计信息脚本右键单击数据库->生成脚本->选择特定的数据库对象->在下一个屏幕中选择高级并选择脚本统计信息并将其粘贴到问题中。使用此信息,任何人都可以复制您面临的相同问题。否则,回答您的问题会变得非常困难。粘贴服务器版本也有助于您在此处向我们展示当前的执行计划:@ramy为您提供一个简单的点击。你试过了吗?这里有两个相似的子集。此外,如果前面的说明没有意义,请分析1索引2列类型的执行计划。干杯,将尝试下面的建议,并更新我的问题必须明确。@cloudsafe不需要重复的明确。它将是唯一的集,没有重复。也许我有误解,但如果同一个人有多个订单呢?@cloudsafe除了的最终结果总是唯一的。我相信这里的任何冗余都会降低性能。请看一个简单的例子。两个查询的结果只有一条记录为1。干杯!这工作正常,但只将我笔记本电脑上的查询时间从12秒减少到11秒左右:执行时间比12秒短。天才谢谢。