sql问题,挑战

时间:2009-12-25 06:26:55

标签: sql greatest-n-per-group

我想要

id   a    b     c
--------------------
1    1    100   90
6    2    50    100

...从:

id   a    b     c
--------------------
1    1    100   90
2    1    300   50
3    1    200   20
4    2    200   30
5    2    300   70
6    2    50    100

这是b组中b组最小的行。

如何使用sql?

修改

我认为可以通过

来实现
select * from table group by a having min(b);

我后来发现这是错误的。

但是可以用having声明吗?

我正在使用MySQL

5 个答案:

答案 0 :(得分:3)

SELECT t1.*
FROM mytable t1
LEFT OUTER JOIN mytable t2
  ON (t1.a=t2.a AND t1.b>t2.b)
WHERE t2.a IS NULL;

这是有效的,因为应该没有匹配的行t2具有相同的a和较小的b


更新:此解决方案与其他人确定的关联问题相同。但是,我们可以打破关系:

SELECT t1.*
FROM mytable t1
LEFT OUTER JOIN mytable t2
  ON (t1.a=t2.a AND (t1.b>t2.b OR t1.b=t2.b AND t1.id>t2.id))
WHERE t2.a IS NULL;

假设例如在平局的情况下,具有较低id的行应该是我们选择的行。


这不能解决问题:

select * from table group by a having min(b);

因为HAVING MIN(b)仅测试组中的最小值不为假(在MySQL中表示不为零)。 HAVING子句中的条件是从结果中排除组,而不是选择要返回的组中的行。

答案 1 :(得分:3)

在MySQL中:

select t1.* from test as t1
inner join
(select t2.a, min(t2.b) as min_b from test as t2 group by t2.a) as subq
on subq.a=t1.a and subq.min_b=t1.b;

以下是证据:

mysql> create table test (id int unsigned primary key auto_increment, a int unsigned not null, b int unsigned not null, c int unsigned not null) engine=innodb;
Query OK, 0 rows affected (0.55 sec)

mysql> insert into test (a,b,c) values (1,100,90), (1,300,50), (1,200,20), (2,200,30), (2,300,70), (2,50,100);
Query OK, 6 rows affected (0.39 sec)
Records: 6  Duplicates: 0  Warnings: 0

mysql> select * from test;
+----+---+-----+-----+
| id | a | b   | c   |
+----+---+-----+-----+
|  1 | 1 | 100 |  90 |
|  2 | 1 | 300 |  50 |
|  3 | 1 | 200 |  20 |
|  4 | 2 | 200 |  30 |
|  5 | 2 | 300 |  70 |
|  6 | 2 |  50 | 100 |
+----+---+-----+-----+
6 rows in set (0.00 sec)

mysql> select t1.* from test as t1 inner join (select t2.a, min(t2.b) as min_b from test as t2 group by t2.a) as subq on subq.a=t1.a and subq.min_b=t1.b;
+----+---+-----+-----+
| id | a | b   | c   |
+----+---+-----+-----+
|  1 | 1 | 100 |  90 |
|  6 | 2 |  50 | 100 |
+----+---+-----+-----+
2 rows in set (0.00 sec)

答案 2 :(得分:1)

使用:

SELECT DISTINCT
       x.*
  FROM TABLE x
  JOIN (SELECT t.a,
               MIN(t.b) 'min_b'
          FROM TABLE T
      GROUP BY t.a) y ON y.a = x.a
                     AND y.min_b = x.b

答案 3 :(得分:0)

你是对的。选择min(b),a从表组中选择a。如果您想要整行,那么您就使用了分析功能。这取决于数据库s / w。

答案 4 :(得分:0)

这取决于实现,但这通常比自连接方法更快:

SELECT id, a, b, c
FROM
    (
        SELECT id, a, b, c
        , ROW_NUMBER() OVER(PARTITION BY a ORDER BY b ASC) AS [b IN a]
    ) As SubqueryA
WHERE [b IN a] = 1

当然,它确实要求您的SQL实现与标准保持最新。