0

MySQL: Выбор строк при первом вхождении каждого уникального значения

11

Описание проблемы

У меня есть следующая таблица, в которой интересующая нас колонка — это cid:

+-----+-------+-------+-------+---------------------+--------------+
| cid | pid   | rid   | clink | time                | snippet      |
+-----+-------+-------+-------+---------------------+--------------+
| 155 | 11222 |  1499 |  1137 | 2012-08-22 03:05:06 | hi           |
| 138 | 11222 |   241 |  1136 | 2012-08-21 05:25:00 | again        |
| 138 | 11222 |   241 |  1135 | 2012-08-21 05:16:40 | hi           |
| 155 | 11222 |  1499 |  1134 | 2012-08-21 05:11:00 | hi cute      |
| 140 | 11222 | 11223 |  1133 | 2012-08-21 05:05:18 | hi           |
| ... | ...   | ...   | ...   | ...                 | ...          |
+-----+-------+-------+-------+---------------------+--------------+

Мне нужно извлечь только первое вхождение каждого уникального cid. В результате должна получиться таблица, которая будет выглядеть следующим образом:

+-----+-------+-------+-------+---------------------+--------------+
| cid | pid   | rid   | clink | time                | snippet      |
+-----+-------+-------+-------+---------------------+--------------+
| 155 | 11222 |  1499 |  1137 | 2012-08-22 03:05:06 | hi           |
| 138 | 11222 |   241 |  1136 | 2012-08-21 05:25:00 | again        |
| 140 | 11222 | 11223 |  1133 | 2012-08-21 05:05:18 | hi           |
| 154 | 11222 |   565 |  1132 | 2012-08-21 05:04:47 | 7            |
| 153 | 11222 |   272 |  1131 | 2012-08-21 05:04:41 | 6            |
| ... | ...   | ...   | ...   | ...                 | ...          |
+-----+-------+-------+-------+---------------------+--------------+

Как я могу написать запрос, чтобы получить только первые вхождения для каждого cid?

4 ответ(ов)

0

В MySQL есть "хака" для этой задачи:

SELECT *
FROM mytable
GROUP BY cid;

Это всё, что вам нужно, потому что в MySQL разрешено не агрегировать столбцы, которые не входят в GROUP BY (в других СУБД это вызвало бы ошибку синтаксиса). В этом случае MySQL вернет только первое совпадение для каждого значения в GROUP BY. Однако стоит отметить, что это не гарантирует, каким образом выбирается "первое" совпадение — это будет зависеть от порядка чтения строк.

Если вы хотите получить определённое первое совпадение, сначала нужно отсортировать строки, а затем применить "хака" с группировкой:

SELECT *
FROM (
    -- сортируем по столбцу "time" в порядке убывания, чтобы получить "самую последнюю" строку
    SELECT * FROM mytable ORDER BY time DESC
) x
GROUP BY cid;

Таким образом, вы сможете получить именно ту строку, которая вам нужна!

0

Вы можете использовать следующий SQL-запрос, чтобы получить записи с минимальным значением времени для каждой группы:

SELECT *
FROM tableName a 
INNER JOIN (
    SELECT cid, MIN(`time`) AS MinTime
    FROM tableName
    GROUP BY cid
) b 
ON a.cid = b.cid AND a.time = b.MinTime

В этом запросе мы сначала создаем подзапрос, который выбирает cid и минимальное время (MinTime) для каждой группы cid. Затем мы выполняем внутреннее соединение с основной таблицей (tableName), используя условия на совпадение cid и значения времени. Это позволит вам получить все строки из оригинальной таблицы, которые имеют минимальное время для каждого cid.

0

Я понимаю, что это старая тема, но у меня возникла проблема с тем, что предложенное решение возвращает только столбцы, в которых более одного вхождения.

Вот что сработало для меня:

SELECT cid, pid, rid, clink, MAX(time), snippet 
FROM mytable 
GROUP BY cid

Такой запрос позволяет получить столбцы, которые мне нужны, включая MAX(time), и группирует результаты по колонке cid. Надеюсь, это поможет и другим с подобной задачей!

0

Вы можете использовать фильтрующее соединение:

SELECT *
FROM (
        SELECT cid,
               MIN(time) AS min_time
        FROM YourTable
        GROUP BY cid
) AS filter
JOIN YourTable AS yt
ON filter.cid = yt.cid
   AND filter.min_time = yt.time

Этот запрос сначала создает подзапрос, который выбирает минимальное время для каждого cid, а затем выполняет соединение с основной таблицей YourTable, чтобы получить все соответствующие записи.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь