4

表:贷款

Loan_no     Amount        SSS_no              Loan_date

7           700.00        0104849222          2010-01-03 
8           200.00        0104849222          2010-02-28
9           300.00        0119611199          2010-11-18
10          150.00        3317131410          2012-11-28
11          600.00        0104849222          2011-01-03
14          175.00        3317131410          2012-12-05
15          260.00        3317131410          2013-02-08
16          230.00        0104849222          2013-03-06
17          265.00        0119611199          2011-04-30
18          455.00        3317131410          2013-03-10

期望的结果:

我想检索每个人提供的最新贷款(由他们的 SSS 编号标识)。结果应如下所示:

Loan_no           Amount                SSS_no                Loan_date

16                230.00              0104849222              2013-03-06
17                265.00              0119611199              2011-04-30
18                455.00              3317131410              2013-03-10

使用的查询#1:

SELECT * FROM loan GROUP BY SSS_no ORDER BY Loan_date DESC

MYSQL 结果

Loan_no             Amount              SSS_no                  Loan_date

10                  150.00            3317131410                2012-11-28
9                   300.00            0119611199                2010-11-18
7                   700.00            0104849222                2010-01-03

使用的查询#2:

SELECT Loan_no, Amount, SSS_no, max(Loan_date) FROM loan GROUP BY SSS_no

MYSQL 结果

Loan_no            Amount                SSS_no                Loan_date

7                  700.00                0104849222            2013-03-06
9                  300.00                0119611199            2011-04-30
10                 150.00                3317131410            2013-03-10

有人可以帮我解决我的问题吗?谢谢。

4

3 回答 3

1

MySQL 参考建议了几种解决此问题的方法。最简单的是子查询:

SELECT *
FROM   loan l1
WHERE  loan_date=(SELECT MAX(l2.loan_date)
              FROM loan l2
              WHERE l1.sss_no = l2.sss_no);

鉴于这种类型的子查询可能性能不佳,他们还建议使用JOIN(基本上是 Mahmoud Gamal 的答案):

SELECT l1.loan_no, l1.amount, l1.sss_no, l1.loan_date
FROM loan l1
JOIN (
  SELECT loan_no, MAX(loan_date) AS loan_date
  FROM loan
  GROUP BY sss_no) AS l2
  ON l1.loan_date = l2.loan_date AND l1.sss_no = l2.sss_no;

第三种选择是:

SELECT l1.loan_no, l1.amount, l1.sss_no, l1.loan_date
FROM loan l1
LEFT JOIN loan l2 ON l1.sss_no = l2.sss_no AND l1.loan_date < l2.loan_date
WHERE l2.sss_no IS NULL;

工作的LEFT JOIN基础是,当l1.loan_date处于最大值时,有后面l2.loan_date,所以 l2 行值将为 NULL。

所有这些都应该具有相同的输出,但性能可能不同。

于 2013-03-25T11:14:18.287 回答
1

试试这个:

SELECT l1.*
FROM loan AS l1
INNER JOIN
(
   SELECT SSS_no, MAX(Loan_date) LatestDate
   FROM loan
   GROUP BY SSS_no
) AS l2  ON l1.SSS_no    = l2.SSS_no 
        AND l1.loan_date = l2.LatestDate;

SQL 小提琴演示

这会给你:

| LOAN_NO | AMOUNT |     SSS_NO |  LOAN_DATE |
----------------------------------------------
|      16 |    230 |  104849222 | 2013-03-06 |
|      17 |    265 |  119611199 | 2011-04-30 |
|      18 |    455 | 3317131410 | 2013-03-10 |
于 2013-03-25T10:58:45.873 回答
1

您得到意外结果的原因是因为您GROUP BY仅在列表中的一列上使用 aSELECT并且您没有在所有列上使用任何聚合函数。

MySQL 对该函数使用了扩展,GROUP BY当您不这样做GROUP BY或聚合SELECT列表中的所有项目时,可能会导致意外结果。(参见MySQL 对 GROUP BY 的扩展

来自 MySQL 文档:

MySQL 扩展了 GROUP BY 的使用,以便选择列表可以引用未在 GROUP BY 子句中命名的非聚合列。...您可以使用此功能通过避免不必要的列排序和分组来获得更好的性能。但是,这主要在每个未在 GROUP BY 中命名的非聚合列中的所有值对于每个组都相同时很有用。服务器可以从每个组中自由选择任何值,因此除非它们相同,否则选择的值是不确定的。此外,从每个组中选择值不会受到添加 ORDER BY 子句的影响。在选择了值之后对结果集进行排序,并且 ORDER BY 不会影响服务器选择的值。

您可以确保返回正确结果的唯一方法是更改​​您的查询以GROUP BY正确聚合。

所以你可以使用类似的东西:

select l1.loan_no,
  l1.amount,
  l1.SSS_no,
  l1.loan_date
from loan l1
inner join
(
  select SSS_no, max(loan_date) Loan_date
  from loan
  group by SSS_no
) l2
  on l1.SSS_no = l2.SSS_no
  and l1.loan_date = l2.loan_date

请参阅带有演示的 SQL Fiddle

这实现了一个子查询来获取max(loan_date)for each SSS_noSSS_no然后,此子查询会在 the和 max上连接回您的表,loan_date这将保证您为每个SSS_no.

于 2013-03-25T11:21:17.913 回答