【问题标题】:Groupwise maximum分组最大值
【发布时间】:2013-02-19 03:02:31
【问题描述】:

我有一个表,我试图从中检索每种证券的最新位置:

桌子:

我创建表的查询:SELECT id, security, buy_date FROM positions WHERE client_id = 4

+-------+----------+------------+
| id    | security | buy_date   |
+-------+----------+------------+
|    26 | PCS      | 2012-02-08 |
|    27 | PCS      | 2013-01-19 |
|    28 | RDN      | 2012-04-17 |
|    29 | RDN      | 2012-05-19 |
|    30 | RDN      | 2012-08-18 |
|    31 | RDN      | 2012-09-19 |
|    32 | HK       | 2012-09-25 |
|    33 | HK       | 2012-11-13 |
|    34 | HK       | 2013-01-19 |
|    35 | SGI      | 2013-01-17 |
|    36 | SGI      | 2013-02-16 |
| 18084 | KERX     | 2013-02-20 |
| 18249 | KERX     | 0000-00-00 |
+-------+----------+------------+

我一直在搞乱基于this page 的查询版本,但我似乎无法得到我正在寻找的结果。

这是我一直在尝试的:

SELECT t1.id, t1.security, t1.buy_date 
FROM positions t1
WHERE buy_date = (SELECT MAX(t2.buy_date)
                    FROM positions t2
                    WHERE t1.security = t2.security)

但这只是返回我:

+-------+----------+------------+
| id    | security | buy_date   |
+-------+----------+------------+
|    27 | PCS      | 2013-01-19 |
+-------+----------+------------+

我正在尝试获取每种证券的最大/最晚购买日期,因此结果中每一种证券的购买日期都是最近的一行。非常感谢任何帮助。

编辑:位置的 id 必须与最大购买日期一起返回。

【问题讨论】:

  • @Hogan 可能是这样。我已经有一段时间没有这样的要求了,你的当然要正确得多。
  • 请使用您在 cmets 中提供的所有详细信息编辑问题。这样会更清楚一点。

标签: mysql sql


【解决方案1】:

您可以使用此查询。您可以在 75% 的时间内取得成果。我检查了更多的数据集。子查询需要更多时间。

SELECT p1.id, 
       p1.security, 
       p1.buy_date 
       FROM positions p1
left join
            positions p2
                on p1.security = p2.security
                   and p1.buy_date < p2.buy_date
      where 
      p2.id is null;

SQL-Fiddle link

【讨论】:

  • 就我而言,这是最好的答案,尽管前一个标记为答案,但效率更高。干得好。
  • 感谢@Grep 的好话 :) 听到这样的鼓励总是很高兴。 :)
  • @VishalZanzrukia 你的回答是最好的,我已经更新了对你的回答,给出了相同的结果,效率更高。
【解决方案2】:

您可以使用子查询来获取结果:

SELECT p1.id, 
  p1.security, 
  p1.buy_date 
FROM positions p1
inner join
(
  SELECT MAX(buy_date) MaxDate, security
  FROM positions 
  group by security
) p2
  on p1.buy_date = p2.MaxDate
  and p1.security = p2.security

SQL Fiddle with Demo

或者您可以在WHERE 子句中使用以下内容:

SELECT t1.id, t1.security, t1.buy_date 
FROM positions t1
WHERE buy_date = (SELECT MAX(t2.buy_date)
                  FROM positions t2
                  WHERE t1.security = t2.security
                  group by t2.security)

SQL Fiddle with Demo

【讨论】:

  • 这似乎也很有用。感谢您的输入@bluefeet
  • @Tomanow 不同的是,这将返回与max(buy_date)关联的id
  • @bluefeet 我正在按我没有提到的 client_id = 4 进行过滤,因为如果我不这样做,该表将返回数千行。当我将过滤器添加到您的查询中时,我仍然只得到一个条目,即我原始帖子中的 PCS 行。
  • @Tomanow 请使用您正在使用的查询和一些匹配的示例数据编辑您的帖子。你的 OP 不包括 client_id 所以我现在猜。 :)
  • 我明白你对 Hogan 的回答的意思,它没有从最大日期的位置输出正确的 id。
【解决方案3】:

这是通过一个简单的 group by 完成的。您想按证券分组并获得buy_date 的最大值。 SQL:

SELECT security, max(buy_date) 
from positions
group by security

注意,这比bluefeet's answer 快,但不显示 ID。

【讨论】:

  • @Marian - 输出显示为错误结果,而不是预期结果。
  • @Hogan,结果没有为我提供最大买入日期头寸的正确 ID。这是输出,您可以看到日期不匹配。
  • +-------+----------+------------+--------------+ | id | security | buy_date | max_buy_date | +-------+----------+------------+--------------+ | 32 | HK | 2012-09-25 | 2013-01-19 | | 18084 | KERX | 2013-02-20 | 2013-02-20 | | 26 | PCS | 2012-02-08 | 2013-01-19 | | 28 | RDN | 2012-04-17 | 2012-09-19 | | 35 | SGI | 2013-01-17 | 2013-02-16 | +-------+----------+------------+--------------+
  • @Tomanow - 我的解决方案不返回 ID - 如果您想要 ID,请使用 bluefeet 的答案。他的速度会慢一些,但如果你需要,你会得到 ID。
  • @Marian - 几年后我已经习惯了。 :)
【解决方案4】:

@bluefeet 的回答还有另外两种方法可以获得您想要的结果 - 第一种可能比您的查询更有效。

我不明白你为什么说你的查询不起作用。它看起来很不错,并返回了预期的结果。在 SQL-Fiddle

测试
SELECT t1.id, t1.security, t1.buy_date 
FROM positions t1
WHERE buy_date = ( SELECT MAX(t2.buy_date)
                   FROM positions t2
                   WHERE t1.security = t2.security ) ;

如果在添加client_id = 4 条件时出现问题,那是因为您只在一个WHERE 子句中添加它,而您必须在两个子句中都添加它:

SELECT t1.id, t1.security, t1.buy_date 
FROM positions t1
WHERE client_id = 4
  AND buy_date = ( SELECT MAX(t2.buy_date)
                   FROM positions t2
                   WHERE client_id = 4
                     AND t1.security = t2.security ) ;

【讨论】:

    【解决方案5】:
    select security, max(buy_date) group by security from positions;
    

    您只需要获得每种证券的最大购买日期(当您大声说出您想要从查询中得到什么并包含短语“for each x”时,您可能希望在 x 上进行分组)

    当您使用group by 时,您的选择中的所有列必须是已分组或聚合的列,因此,例如,如果您想包含 id,您可能必须使用类似的子查询与你之前的一样,因为似乎没有任何聚合可以合理地用于 id,而另一个 group by 会给你太多的行。

    【讨论】:

    • 从哪个表中获取?
    • 不是,因为他要的是最新的位置(不是最新的日期),所以日期最高的行的ID
    猜你喜欢
    • 2018-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-08
    • 1970-01-01
    • 1970-01-01
    • 2013-10-24
    相关资源
    最近更新 更多