我在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
我对SQL很陌生,想要了解我是否有效地执行此操作。我最终在一个选择查询中将这样的子查询加入到customers表中,并且可能需要几十分钟才能运行。
我是在高效地做这件事还是可以改进?例如,我不确定我在订单表中的id上的索引是否有用,也许我可以通过先创建子查询中的内容的临时表并在id中创建唯一索引来加快查询速度。临时表,以便SQL Server知道id
现在是一个唯一的列,然后将我的customers表连接到此临时表?我通常在客户和订单表中有一两百万行。
非常感谢提前!
答案 0 :(得分: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
在您的上述查询中,您需要小心放置括号的位置,因为我认为它不起作用。此外,您在结果中返回产品,但不包括在嵌套子查询中。
答案 1 :(得分:2)
对于刚学习SQL的人来说,你的查询看起来很不错。
客户的索引可能会也可能不会用于查询 - 您需要查看执行计划。 orders(id, order_date)
上的索引可以非常有效地用于row_number
函数。
一个评论是关于字段的命名。字段orders.id
不应该是客户ID。这应该是'orders.Customer_Id`。保持命名系统在表之间保持一致将在未来帮助您。
答案 2 :(得分:0)
试试这个......很容易理解
;WITH cte
AS (
SELECT id
,product
,order_id
,ROW_NUMBER() OVER (
PARTITION BY id ORDER BY Order_Date ASC
) AS order_No
FROM orders
)
SELECT c.id
,c.country
,c1.Product
,c1.order_id
FROM customers c
INNER JOIN cte c1 ON c.id = c1.id
WHERE c1.order_No = 1