将子查询转换为连接

时间:2013-11-27 19:04:36

标签: mysql sql sql-server

我有三个表:userProfileloginTimesorders

我正在尝试获取每个用户的个人资料行,他的上次登录时间以及他的最后一个订单行。

这是我的疑问:

Select u.*, t.loginTime, orders.* From userProfiles u 

Inner Join

(Select userId, MAX(time) loginTime From loginTimes Group By userID) t

On u.userId = t.userID

Inner Join
(Select userId, MAX(enterDate) orderDate From orders Group By userId) o

On u.userID = o.userID

Inner Join 
orders On orders.userId = u.userId And orders.enterDate = o.orderDate

有没有办法在没有这么多子查询的情况下重写?

3 个答案:

答案 0 :(得分:1)

OP我认为这是您要查询的查询,这仍然需要2个子查询,但我不相信您的原始查询按预期运行。

您可以移除loginTimes子查询,并在外部MAX(loginTime)列表中使用SELECT,但是您需要GROUP BY order中的每个字段表,这可以说是不洁净的。

以下查询检索用户最近订单的UserId,最新LoginTime和整个order记录:

SELECT u.userId, 
       u.userName,
       l.loginTime,
       o.* 
FROM userProfiles u 
INNER JOIN ( SELECT userId, 
                   loginTime = MAX(time) 
             FROM loginTimes 
             GROUP BY userID) l ON u.userId = l.userId
INNER JOIN ( SELECT *,
             rowNum = ROW_NUMBER() OVER (PARTITION BY userId 
                                         ORDER BY enterDate DESC) 
             FROM orders) o ON u.userId = o.userId AND o.rowNum = 1

Working on SQLFiddle

答案 1 :(得分:0)

我相信这样做:

SELECT u.userID
      ,u.otherColumn
      ,MAX(t.time) AS loginTime
      ,MAX(o.enterDate) AS orderDate
FROM userProfiles u
JOIN loginTimes t ON t.userID = u.userID
JOIN orders o ON o.userID = u.userID
GROUP BY u.userID, u.otherColumn

对于您添加到SELECT子句的userProfiles中的每个其他列,您还需要将它添加到GROUP BY子句中。

<强>更新

只是因为它可以完成..我在没有任何子查询的情况下尝试过它:)

SELECT u.userID
      ,MAX(t.time) AS loginTime
      ,o.*
FROM userProfiles u
JOIN loginTimes t ON t.userID = u.userID
JOIN orders o ON o.userID = u.userID
LEFT JOIN orders o1 ON o.userID = o1.userID AND o.enterDate < o1.enterDate
WHERE o1.orderID IS NULL
GROUP BY u.userID
        ,o.* --write out the fields here

您还必须在select子句的GROUP BY子句中记下所需的订单表的字段。

答案 2 :(得分:0)

您可以使用以下内容轻松重写聚合。

-- Aggregation 

(
SELECT
  T.userId, 
  MAX(time) as loginTime,
  MAX(enterDate) as orderDate
FROM
  loginTimes as T INNER JOIN orders as O
ON
  T.userId = O.userId
GROUP BY 
  T.userId
)

但是,我不明白为什么要计算MAX(enterDate)而不使用它。

在没有聚合的情况下连接的两个表也很容易。你应该远离使用*。如果没有使用所有字段,那就是浪费开销。

SELECT 
  U.*, O.* 
FROM 
  userProfiles as U
INNER JOIN
  orders as O 
ON O.userId = U.userId

请解释您尝试从查询中返回的值。 什么是业务逻辑?

相关问题