SQL查询最大日期

时间:2011-03-13 20:27:38

标签: sql join left-join

我问a related question我得到了一些非常好的答案,但是我试图在不制作临时表的情况下进行查询。我相信它可以做到,但我无法弄清楚如何去做。

我有两个表,我希望获得每个条目的最新状态,其中状态日期小于或等于输入日期。

条目表(条目):

  UserID   | EntryDate  
 ----------------------
    1      |  5/4/2010  
    1      |  4/4/2010  
    1      |  3/4/2010  
    1      |  2/4/2010  
    2      |  5/4/2010
    2      |  4/4/2010

条目状态表(状态):

  UserID   | StatusDate  | Detail
  -------------------------------
    1      |  5/28/2010  |  D-1
    1      |  4/24/2010  |  D-2
    1      |  4/5/2010   |  D-3
    1      |  2/28/2010  |  D-4

预期输出:

UserID | EntryDate | Detail
---------------------------
  1    | 5/4/2010  |  D-2
  1    | 4/4/2010  |  D-4
  1    | 3/4/2010  |  D-4
  1    | 2/4/2010  | <NULL>

在我的previous question中,您可以看到我的努力和相关答案,但我已经缩小了问题范围以简化问题。

我试图做这样的事情(但我知道我必须离开):

         SELECT E.EntryDate, 
                S.Detail, 
                MAX(S.StatusDate) AS MaxStatusDate
           FROM Entry AS E 
LEFT OUTER JOIN Status AS S ON E.EntryDate >= S.StatusDate

4 个答案:

答案 0 :(得分:3)

我想你想要像

这样的东西
SELECT E.UserID
    , E.EntryDate
    , (SELECT TOP 1 Detail
       FROM Status AS S
       WHERE S.UserID = E.UserID
       AND S.StatusDate <= E.EntryDate
       ORDER BY S.StatusDate DESC)
FROM Entry AS E

如果您的数据库不支持TOP或出于性能原因,您宁愿避免ORDER BY尝试类似的内容:

SELECT E.UserID
    , E.EntryDate
    , (SELECT S1.Detail
       FROM Status AS S1
       WHERE S1.UserID = E.UserID
       AND S1.StatusDate = (SELECT MAX(S2.StatusDate)
                            FROM Status AS S2
                            WHERE S2.UserID = E.UserID
                            AND S2.StatusDate <= E.EntryDate))
FROM Entry AS E

答案 1 :(得分:1)

我不认为这是一种通用的方法,但在某些SQL方言中,您可以在子查询中使用TOP或LIMIT从第一个匹配记录中的列中获取值在另一列的排序(ORDER BY)上。

例如......

SELECT
  Entry.*,
  ( SELECT TOP 1 
      Status.Detail
    FROM Status
    WHERE
      Entry.UserID = Status.UserID AND
      Entry.EntryDate >= Status.StatusDate
    ORDER BY
      Entry.EntryDate
  ) As StatusDetail

答案 2 :(得分:1)

row_number方式,适用于支持它的数据库:

SELECT  *
FROM    (
        SELECT  ROW_NUMBER() OVER (
                    PARTITION BY e.UserId, e.EntryDate
                    ORDER BY s.StatusDate desc) as rn
        ,       *
        FROM    Entry e
        INNER JOIN    
                Status s
        ON      s.UserID = e.UserID
                AND s.StatusDate <= e.EntryDate
        ) as SubQueryAlias
where   rn = 1

答案 3 :(得分:1)

SELECT
  e.UserID,
  e.EntryDate,
  s.Detail
FROM Entry e
  INNER JOIN (SELECT DISTINCT UserID FROM Status) u
    ON e.UserID = u.UserID
  LEFT JOIN (
    SELECT
      e.UserID,
      e.EntryDate,
      MAX(s.StatusDate) AS StatusDate
    FROM Entry e
      INNER JOIN Status s
        ON e.UserID = s.UserID AND e.EntryDate >= s.StatusDate
    GROUP BY e.UserID, e.EntryDate
  ) sd
    ON e.UserID = sd.UserID AND e.EntryDate = sd.EntryDate
  LEFT JOIN Status s
    ON sd.UserID = s.UserID AND sd.StatusDate = s.StatusDate

不同用户列表用于过滤掉Entry中未在Status中显示的用户。

然后,结果集与派生表连接,该派生表包含与输入日期对应的最大状态日期值。

最后再次加入Status表,这次是为了获取详细信息。

最后两个连接是左连接,因此结果集将包含EntryStatus的每个用户的所有行,并且内连接保证所有用户都不会其他人。