проблема sql, вызов - PullRequest
       28

проблема sql, вызов

2 голосов
/ 25 декабря 2009

Я хочу получить

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 на a.

Как это сделать с помощью sql?

EDIT

Я думал, что это может быть достигнуто

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

что я обнаружил позже, это неправильно.

Но возможно ли это сделать с помощью оператора having?

Я использую MySQL

Ответы [ 5 ]

3 голосов
/ 25 декабря 2009

В 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)
3 голосов
/ 25 декабря 2009
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 голос
/ 25 декабря 2009

Использование:

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
0 голосов
/ 25 декабря 2009

Это зависит от реализации, но обычно это быстрее, чем метод самосоединения:

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 была достаточно современной со стандартом.

0 голосов
/ 25 декабря 2009

Ты прав. выберите min (b), a из таблицы таблиц по a. Если вы хотите всю строку, то вы используете функцию аналитики. Это зависит от базы данных з / ш.

...