MySql条件组

时间:2011-08-12 08:34:57

标签: mysql group-by case-when

请考虑我的表格(这只是一个简化版本,在我的项目中,我有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 个答案:

答案 0 :(得分:5)

尝试这个

    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

答案 1 :(得分:0)

试试这个。我看到的唯一减速因素是最终排序 - 所以你可以先试用它而不用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