MySQL MIN / MAX возвращает правильное значение, но не связанную информацию записи - PullRequest
3 голосов
/ 22 февраля 2011

Я действительно застрял на этом.Я явно не понимаю концепцию MIN / MAX.

Я пытаюсь получить последнюю строку из группы work_type и work_id.

Если я изменяю с MIN на MAX, он меняет возвращенную метку времени, но никогда не возвращает информацию о состоянии изэта запись.

Пример:

"SELECT 
    CONCAT(work_type, work_id) AS condition_id, 
    status,
    MIN(created_timestamp) as latest
  FROM conditions
  GROUP BY condition_id"

С MIN я получаю:

    Array
    (
        [0] => Array
            (
                [condition_id] => cutouts00002
                [status] => bad
                [latest] => 2011-02-21 15:20:27
            )

        [1] => Array
            (
                [condition_id] => paintings00002
                [status] => damagez
                [latest] => 2011-02-21 14:43:35
            )

    )

С MAX я получаю:

Array
(
    [0] => Array
        (
            [condition_id] => cutouts00002
            [status] => bad
            [latest] => 2011-02-21 15:22:20
        )

    [1] => Array
        (
            [condition_id] => paintings00002
            [status] => damagez
            [latest] => 2011-02-21 14:43:41
        )

)

Buдело в том, что статус в строке с самой последней отметкой времени - «нет повреждений», но он никогда не возвращает строку, соответствующую MAX (current_timestamp), он только возвращает строку «magez ».

Любая помощь приветствуется.

Спасибо.

Ответы [ 3 ]

2 голосов
/ 22 февраля 2011

Вы стали жертвой слабых правил MySQL, которые допускают включение неагрегатов в запрос GROUP BY.Конечно, вы работаете с MIN или MAX и только ONE одновременно, но рассмотрите этот запрос:

SELECT 
    CONCAT(work_type, work_id) AS condition_id, 
    status,
    MIN(created_timestamp) as earliest,
    MAX(created_timestamp) as latest
  FROM conditions
  GROUP BY condition_id

Теперь подумайте о , какая строка столбец статуса должен исходить из.Абсурдно ставить корреляцию между агрегированными (в GROUP BY) и неагрегированными столбцами.

Вместо этого напишите свой запрос следующим образом

SELECT X.condition_id, C.status, X.earliest
FROM (
  SELECT 
    CONCAT(work_type, work_id) AS condition_id, 
    status,
    MIN(created_timestamp) as earliest
  FROM conditions
  GROUP BY condition_id
) X JOIN conditions C
  on CONCAT(c.work_type, c.work_id) = X.condition_id
  and c.created_timestamp = X.earliest

Но если у вас было две записис той же самой меткой create_time она становится еще сложнее

SELECT X.condition_id, Max(C.status) status, X.earliest
FROM (
  SELECT 
    CONCAT(work_type, work_id) AS condition_id, 
    status,
    MIN(created_timestamp) as earliest
  FROM conditions
  GROUP BY condition_id
) X JOIN conditions C
  on CONCAT(c.work_type, c.work_id) = X.condition_id
  and c.created_timestamp = X.earliest
GROUP BY X.condition_id, X.earliest
0 голосов
/ 02 августа 2012

Я бы предпочел поместить подзапрос в предложение WHERE, так как он читается легче.

SELECT 
    CONCAT(work_type, work_id) AS condition_id, 
    status,
    created_timestamp as latest
FROM
    conditions
WHERE
    created_timestamp = (
        SELECT
            MIN(conditions2.created_timestamp)
        FROM
            conditions AS conditions2
        WHERE
            conditions2.condition_id = conditions.condition_id
    )
GROUP BY
    condition_id

Кроме того, если в первом запросе должно было быть какое-либо дополнительное соединение или предложения where, они могут повторяться вподзапрос.

SELECT 
    CONCAT(work_type, work_id) AS condition_id, 
    status,
    created_timestamp as latest
FROM
    conditions
    INNER JOIN some_table on condition.id = some_table.condition_id
WHERE
    some_table.some_column > 50 AND 
    created_timestamp = (
        SELECT
            MIN(conditions2.created_timestamp)
        FROM
            conditions AS conditions2
            INNER JOIN some_table AS some_table2 on condition2.id = some_table2.condition_id
        WHERE
            some_table.some_column > 50 AND 
            conditions2.condition_id = conditions.condition_id
    )
GROUP BY
    condition_id
0 голосов
/ 22 февраля 2011

Мне, как правило, приходилось делать что-то довольно странное для этого.

Мое решение - T-SQL, но я надеюсь, что вы можете его переделать.

SELECT 
    CONCAT(c.work_type, c.work_id) as condition_id, 
    c.status, 
    c.created_timestamp as latest
FROM conditions c
JOIN (SELECT work_type, work_id, max(current_timestamp) as latest GROUP BY work_type, work_id) c2 
    ON c.work_type = c2.work_type
    AND c.work_id = c2.work_id
    AND c.created_timestampe = c2.latest
...