在SQL Server中加入子查询的效率

use*_*153 6 sql sql-server join subquery left-join

我在SQL Server 2008 R2中有一个客户和订单表.两者都有客户ID(称为id)的索引.我需要返回客户表中所有客户的详细信息以及订单表中的信息,例如第一个订单的详细信息.

我目前在orders表的子查询上加入了我的customers表,子查询返回了我需要的有关订单的信息.例如:

SELECT c.id
        ,c.country      
        ,First_orders.product
        ,First_orders.order_id
FROM customers c

LEFT JOIN   SELECT( id, 
                    product 
            FROM (SELECT    id
                            ,product
                            ,order_id
                            ,ROW_NUMBER() OVER (PARTITION BY id ORDER BY Order_Date asc) as order_No 
                        FROM orders) orders
            WHERE Order_no = 1) First_Orders
ON c.id = First_orders.id
Run Code Online (Sandbox Code Playgroud)

我对SQL很陌生,想要了解我是否有效地做到了这一点.我最终在一个选择查询中将这样的子查询加入到customers表中,并且可能需要几十分钟才能运行.

我这样做有效还是可以改进?例如,我不确定我在订单表中的id上的索引是否有用,也许我可以通过先创建子查询中的内容的临时表并在id中创建唯一索引来加快查询速度.临时表,所以SQL Server知道id现在是一个唯一的列,然后将我的customers表连接到此临时表?我通常在客户和订单表中有一两百万行.

提前谢谢了!

sge*_*des 6

您可以删除一个子查询以使其更有效:

SELECT c.id
        ,c.country      
        ,First_orders.product
        ,First_orders.order_id
FROM customers c
   LEFT JOIN  (SELECT id
                    ,product
                    ,order_id
                    ,ROW_NUMBER() OVER (PARTITION BY id ORDER BY Order_Date asc) as order_No 
               FROM orders) First_Orders
     ON c.id = First_orders.id AND First_Orders.order_No = 1
Run Code Online (Sandbox Code Playgroud)

在上面的查询中,您需要小心放置括号的位置,因为我认为它不起作用.此外,您在结果中返回产品,但不包括在嵌套子查询中.


Gor*_*off 4

对于刚刚学习 SQL 的人来说,你的查询看起来相当不错。

客户索引可能会也可能不会用于查询——您需要查看执行计划。索引 onorders(id, order_date)可以非常有效地用于该row_number函数。

一项评论是关于字段的命名。该字段orders.id不应是客户 ID。这应该类似于“orders.Customer_Id”。保持表之间的命名系统一致将对您将来有所帮助。