MAX加上JOIN的其他数据

时间:2018-01-11 17:08:53

标签: sql sql-server

这应该是一个简单的假设(至少我认为这是几个小时前我开始做的时候)。

我正在尝试从一个表中选择MAX值并将其与另一个表连接以获取相关数据。

我有两张桌子:ACCOUNTS& ACCOUNT_BALANCES

他们是:

ACCOUNTS

 ACC_ID | NAME    | IMG_LOCATION
 ------------------------------------
   0    | Cash    | images/cash.png
   500  | MyBank  | images/mybank.png

ACCOUNT_BALANCES

ACC_ID | BALANCE | UPDATE_DATE
-------------------------------
  500  | 100     | 2017-11-10
  500  | 250     | 2018-01-11
  0    | 100     | 2018-01-05

我希望最终结果如下:

ACC_ID | NAME    | IMG_LOCATION        | BALANCE | UPDATE_DATE
----------------------------------------------------------------
 0     | Cash    |  images/cash.png    | 100     | 2018-01-05
 500   | MyBank  |  images/mybank.png  | 250     | 2018-01-11

我以为我可以从ACCOUNT_BALANCES表中选择MAX(UPDATE_DATE),并加入ACCOUNTS表以获取帐户名称(如上所示),但必须通过分组表示我的最终结果包括来自ACCOUNT_BALANCES的所有记录表

我可以使用此查询仅选择ACCOUNT_BALANCES中最大UPDATE_DATE的记录,但我不能包含余额。

SELECT
    a.ACC_ID,
    a.IMG_LOCATION,
    a.NAME,
    x.UDATE
FROM
    ACCOUNTS a
RIGHT JOIN
    (
        SELECT
            b.ACC_ID,
            MAX(b.UPDATE_DATE) as UDATE
        FROM
            ACCOUNT_BALANCES b
        GROUP BY
            b.ACC_ID
    ) x
ON
    a.ACC_ID = x.ACC_ID 

如果我在上面的查询中包含ACCOUNT_BALANCES.BALANCE(如此):

SELECT
    a.ACC_ID,
    a.IMG_LOCATION,
    a.NAME,
    x.UDATE
FROM
    ACCOUNTS a
RIGHT JOIN
    (
        SELECT
            b.ACC_ID,
            b.BALANCE,
            MAX(b.UPDATE_DATE) as UDATE
        FROM
            ACCOUNT_BALANCES b
        GROUP BY
            b.ACC_ID, b.BALANCE
    ) x
ON
    a.ACC_ID = x.ACC_ID 

返回的结果如下所示:

ACC_ID | NAME    | IMG_LOCATION        | BALANCE | UPDATE_DATE
----------------------------------------------------------------
 0     | Cash    |  images/cash.png    | 100     | 2018-01-05
 500   | MyBank  |  images/mybank.png  | 100     | 2018-01-11
 500   | MyBank  |  images/mybank.png  | 250     | 2018-01-11

显然就是这种情况,因为我在子查询中将BALANCE分组。

我非常犹豫发布这个,因为这似乎是那些已被回答n次的问题,但我已经搜索了很多,但找不到真正帮助我的任何东西。

This one has a really good answer, but isn't exactly what I'm looking for

我显然错过了一些非常简单的东西,即使是正确方向的指针也会有所帮助。谢谢。

3 个答案:

答案 0 :(得分:1)

试试这个

    ;WITH CTE
AS
(
    SELECT
       RN = ROW_NUMBER() OVER(PARTITION BY AC.ACC_ID ORDER BY AB.UPDATE_DATE DESC),
       AC.ACC_ID,
       NAME,
       IMG_LOCATION,
       BALANCE,
       UPDATE_DATE
       FROM ACCOUNTS AC
          INNER JOIN ACCOUNT_BALANCES AB
             ON AC.ACC_ID = AB.ACC_ID
)
SELECT
    *
    FROM CTE     
       WHERE RN = 1

答案 1 :(得分:1)

我认为最简单的方法是outer apply

select a.*, ab.*
from accounts a outer apply
     (select top 1 ab.*
      from account_balances ab
      where ab.acc_id = a.acc_id
      order by ab.update_date desc
     ) ab;

apply实现了技术上所谓的“横向连接”。这是一种非常强大的连接类型 - 类似于相关子查询的泛化。

答案 2 :(得分:0)

接受的答案将有效。但是,对于大型数据集,请尽量避免使用row_number()函数。相反,您可以尝试这样的事情(假设update_date是唯一约束的一部分):

SELECT
    a.Acc_Id,
    a.Name,
    a.Img_Location,
    bDetail.Balance,
    bDetail.Update_Date
FROM 
    @accounts AS a LEFT JOIN 
    (
        SELECT Acc_Id, MAX(Update_Date) AS Update_Date 
        FROM @account_balances AS b 
        GROUP BY Acc_Id
    ) AS maxDate ON a.Acc_Id = maxDate.Acc_Id   
    LEFT JOIN @account_balances AS bDetail ON maxDate.Acc_Id = bDetail.Acc_Id AND 
                                              maxDate.Update_Date = bDetail.Update_Date