【问题标题】:How to convert a query to use joins?如何将查询转换为使用联接?
【发布时间】:2021-02-04 07:24:44
【问题描述】:

我想编写一个查询,该查询使用“加入概念”来为每个订单返回自同一客户的上一个订单以来经过的天数。

我正在使用AdventureWorks2017数据库,表Sales.SalesOrderHeader

我尝试了以下代码,但实际上我希望通过连接概念来实现:

select customerid,
    orderdate,
    salesorderid,
    datediff(day, 
            (select top(1) s1.orderdate 
             from  sales.SalesOrderHeader s1
             where s1.CustomerID=s.CustomerID
                   and (s1.OrderDate = s.Orderdate 
                       and s1.SalesOrderID < s.Salesorderid
                       or  s1.OrderDate < s.orderdate)
             order by s1.orderdate desc,s1.SalesOrderID desc
             ),
            orderdate) as Daysdifference  
    from sales.SalesOrderHeader s  
    order by CustomerID,OrderDate,SalesOrderID

【问题讨论】:

  • 它嵌套WHERE 对吗?这里有...AND...OR...AND (s1.OrderDate = s.Orderdate AND s1.SalesOrderID &lt; s.Salesorderid OR s1.OrderDate &lt; s.orderdate)

标签: sql sql-server lateral-join


【解决方案1】:

从您现有的查询开始,一种简单的方法是使用横向连接:

select s.customerid, s.orderdate, s.salesorderid,
    datediff(day, s.orderdate, s1.orderdate) days_difference
from sales.salesorderheader s
cross apply (
    select top(1) s1.orderdate 
    from sales.salesorderheader s1
    where s1.customerid = s.customerid
    and (s1.orderdate < s.orderdate) or (s1.orderdate = s.orderdate and s1.id < s.id)
    order by s1.orderdate desc, s1.id desc
) s1

这回答了您关于如何使用连接实现逻辑的问题。不过,让我指出,使用lag() 会更有效地表达这一点:

select customerid, orderdate, salesorderid,
    datediff(day, orderdate, lag(orderdate) over(partition by customer_id order by order_date, id) days_difference
from sales.salesorderheader s

【讨论】:

  • 我想使用任何 ansi 格式的连接,比如内连接或外连接,并且代码中不应该有子查询
  • 这是不正确的答案,它没有显示天之间的差异
【解决方案2】:

我会这样写

SELECT s.CustomerID,
       s.OrderDate,
       s.SalesorderID,
       datediff(day, s1.OrderDate, s.OrderDate) as Daysdifference  
FROM sales.SalesOrderHeader s
OUTER APPLY (
  SELECT top(1) s1.OrderDate-- maybe MAX(s1.OrderDate) ?
  FROM sales.SalesOrderHeader s1
  WHERE s1.CustomerID = s.CustomerID
    AND ((s1.OrderDate = s.OrderDate 
          AND s1.SalesOrderID < s.SalesOrderID) -- I've added parenthesis
       OR  s1.OrderDate < s.OrderDate)
  ORDER BY s1.OrderDate DESC, s1.SalesOrderID DESC
) s1
ORDER BY s.CustomerID, s.OrderDate, s.SalesOrderID

或者类似的东西?

SELECT s.customerID,
       s.orderDate,
       s.SalesOrderID,
       datediff(day, MAX(s1.OrderDate), s.OrderDate) as Daysdifference  
FROM sales.SalesOrderHeader s
LEFT JOIN sales.SalesOrderHeader s1 ON s1.CustomerID = s.CustomerID
                                AND ((s1.OrderDate = s.OrderDate 
                                  AND s1.SalesOrderID < s.SalesOrderID) -- I've added parenthesis
                                OR  s1.OrderDate < s.OrderDate))
GROUP BY s.CustomerID, s.OrderDate, s.salesorderId
ORDER BY s.CustomerID, s.OrderDate, s.SalesOrderID

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-10
    • 1970-01-01
    • 2021-09-16
    • 1970-01-01
    • 2014-12-26
    • 1970-01-01
    相关资源
    最近更新 更多