如何计算行但基于另一列?

时间:2012-10-02 11:57:31

标签: mysql sql

我有这张桌子:

+--------------+-----------------------------+----------------+
| Username     | Message                     | Status         |
+--------------+-----------------------------+----------------+
| jamesbond    | I need some help            | SendingOK      |
| jamesbond    | I need some help            | SendingOK      |
| jamesbond    | I need some help            | SendingFailed  |
| jamesbond    | Mission accomplished        | SendingOK      |
+--------------+-----------------------------+----------------+

由此SQL语法生成:

SELECT A.Username, A.Message, B.Status
FROM db1.SmsBroadcast as A
INNER JOIN db2.sentitems as B 
ON A.MessageSMS1 = B.TextDecoded
WHERE A.Username = 'jamesbond'
GROUP BY Message, Status

现在如何获得此输出?

+--------------+-----------------------------+-----------+---------------+
| Username     | Message                     | SendingOK | SendingFailed |
+--------------+-----------------------------+-----------+---------------+
| jamesbond    | I need some help            | 2         | 1             |
| jamesbond    | Mission accomplished        | 1         | 0             |
+--------------+-----------------------------+-----------+---------------+

SendingOKSendingFailed列实际上可以使用COUNT(*)计算,但我不知道如何基于相同的Message进行计数,而这些消息是以相同的SQL语法执行的。任何想法怎么做?

3 个答案:

答案 0 :(得分:3)

试试这个:

SELECT A.Username, A.Message,
   SUM(CASE WHEN B.Status = 'SendingOK' THEN 1 ELSE 0 END) AS SendingOK ,
   SUM(CASE WHEN B.Status = 'SendingFailed' THEN 1 ELSE 0 END) AS SendingFailed,
FROM db1.SmsBroadcast as A
INNER JOIN db2.sentitems as B ON A.MessageSMS1 = B.TextDecoded
WHERE A.Username = 'jamesbond'
GROUP BY A.Username, A.Message 

答案 1 :(得分:2)

如果您有一定数量的值可以转换为列,那么您可以像其他答案一样对它们进行硬编码。但如果您的号码未知,则可以使用prepared statements

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'SUM(case when Status = ''',
      Status,
      ''' then 1 else 0 end) AS ',
      Status
    )
  ) INTO @sql
FROM db2.sentitems;

SET @sql = CONCAT('SELECT A.Username, A.Message, ', @sql, ' 
                  FROM db1.SmsBroadcast A
                  INNER JOIN db2.sentitems B 
                    ON A.MessageSMS1 = B.TextDecoded
                  WHERE A.Username = ''jamesbond''
                  GROUP BY A.Username, A.Message');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

与此相关的主要区别在于它根据db2.sentitems中的值生成SQL字符串,因此如果值发生更改,则会自动调整,而无需更改代码。

答案 2 :(得分:1)

您只需在CASE声明中使用SELECT,然后usernamemessage对其进行分组。

SELECT `UserName`, 
        `Message`,
        SUM(CASE WHEN `status` = 'SendingOK' THEN 1 ELSE 0 END) OkStat,
        SUM(CASE WHEN `status` = 'SendingFailed' THEN 1 ELSE 0 END) FailedStat
FROM    db1.SmsBroadcast as A
        JOIN db2.sentitems as B 
            ON A.MessageSMS1 = B.TextDecoded
WHERE   A.Username = 'jamesbond'
GROUP BY A.Username, A.Message