MySql Условная группа по - PullRequest
       16

MySql Условная группа по

1 голос
/ 12 августа 2011

Пожалуйста, рассмотрите мою таблицу (это просто упрощенная версия, в моем проекте я получил 600 000+ записей):

Id  TransactionId   TransactionTypeId   Description
1   1               1                   Description1
2   1               1                   Description2
3   1               2                   Description3
4   1               2                   Description4
5   1               1                   Description5
6   1               2                   Description6
7   2               1                   Description7
8   2               1                   Description8
9   2               2                   Description9
10  2               2                   Description10

Что мне нужно сделать, это когда TransactionTypeId = 1, мне нужнополучить последние данные из этой таблицы.В противном случае, когда TransactionTypeId <> 1, мне нужно получить их все.

Для этого экземпляра у меня есть этот запрос:

SELECT MAX(T.Id)
    , SUBSTRING_INDEX(GROUP_CONCAT(T.TransactionId ORDER BY T.Id DESC), ',', 1) AS TransactionId
    , SUBSTRING_INDEX(GROUP_CONCAT(T.TransactionTypeId ORDER BY T.Id DESC), ',', 1) AS TransactionTypeId
    , SUBSTRING_INDEX(GROUP_CONCAT(T.Description ORDER BY T.Id DESC), ',', 1) AS Description    
FROM Transactions T
GROUP BY T.TransactionId
    , CASE WHEN T.TransactionTypeId = 1 THEN T.TransactionTypeId END
ORDER BY T.TransactionId, T.TransactionTypeId

И мой желаемый результат будет:

Id  TransactionId   TransactionTypeId   Description
5   1               1                   Description5
3   1               2                   Description3
4   1               2                   Description4
6   1               2                   Description6
8   2               1                   Description8
9   2               2                   Description9
10  2               2                   Description10

Но моя проблема в том, что даже когда TransactionTypeId <> 1, запрос все еще группирует их.

Мой запрос возвращает:

Id  TransactionId   TransactionTypeId   Description
5   1               1                   Description5
6   1               2                   Description6
8   2               1                   Description8
10  2               2                   Description10

Я знаю, что могу использовать UNION здесь,для разделения запросов для столбца TransactionTypeId, но я не могу, мне потребовалось более 5 минут, чтобы получить результаты.Есть ли возможный (если его нет, у меня нет другого выбора, кроме как использовать UNION) способ решить эту проблему?

Спасибо:)

ОБНОВЛЕНИЕ # 1

Вот мой запрос, когда я использую UNION.

SELECT Transaction.Id
    , Transaction.TransactionId
    , Transaction.TransactionTypeId
    , Transaction.Description
FROM (
    SELECT MAX(T.Id)
        , SUBSTRING_INDEX(GROUP_CONCAT(T.TransactionId ORDER BY T.Id DESC), ',', 1) AS TransactionId
        , SUBSTRING_INDEX(GROUP_CONCAT(T.TransactionTypeId ORDER BY T.Id DESC), ',', 1) AS TransactionTypeId
        , SUBSTRING_INDEX(GROUP_CONCAT(T.Description ORDER BY T.Id DESC), ',', 1) AS Description
    FROM Transactions T
    WHERE T.TransactionTypeId = 1
    GROUP BY T.TransactionId

    UNION

    SELECT T.Id
        , T.TransactionId
        , T.TransactionTypeId
        , T.Description
    FROM Transactions T
    WHERE T.TransactionTypeId <> 1
) Transaction
ORDER BY Transaction.TransactionId, Transaction.TransactionTypeId

Ответы [ 2 ]

5 голосов
/ 15 мая 2014

ПОПРОБУЙТЕ С ЭТИМ

    SELECT MAX(T.Id)
    , SUBSTRING_INDEX(GROUP_CONCAT(T.TransactionId ORDER BY T.Id DESC), ',', 1) AS TransactionId
    , SUBSTRING_INDEX(GROUP_CONCAT(T.TransactionTypeId ORDER BY T.Id DESC), ',', 1) AS TransactionTypeId
    , SUBSTRING_INDEX(GROUP_CONCAT(T.Description ORDER BY T.Id DESC), ',', 1) AS Description    
FROM Transactions T
GROUP BY  CASE WHEN T.TransactionTypeId = 1 THEN CONCAT(T.TransactionId,'-',T.TransactionTypeId) ELSE T.Id END
ORDER BY T.TransactionId, T.TransactionTypeId
0 голосов
/ 12 августа 2011

Попробуйте это. Единственный замедляющий фактор, который я вижу, - это окончательная сортировка, так что вы можете попробовать сначала без ORDER BY:

SELECT T.Id
    , T.TransactionId
    , 1 AS TransactionTypeId
    , T.Description
FROM Transactions T
  JOIN
    ( SELECT MAX(Id) AS Id
      FROM Transactions
      WHERE TransactionTypeId = 1
      GROUP BY TransactionId
    ) AS grp
    ON grp.Id = T.Id

UNION ALL

SELECT T.Id
    , T.TransactionId
    , T.TransactionTypeId
    , T.Description
FROM Transactions T
WHERE T.TransactionTypeId <> 1

ORDER BY TransactionId, TransactionTypeId

Вы также можете использовать этот (который не UNION, но имеет OR, поэтому я не могу быть уверен в производительности) запрос:

SELECT T.Id
    , T.TransactionId
    , T.TransactionTypeId
    , T.Description
FROM Transactions T
WHERE T.TransactionTypeId <> 1
   OR NOT EXISTS
      ( SELECT *
        FROM Transactions tm
        WHERE tm.TransactionTypeId = 1
          AND tm.TransactionId = T.TransactionId
          AND tm.Id > T.Id
      )
ORDER BY T.TransactionId, T.TransactionTypeId
...