将多行合并为一列

时间:2015-04-24 13:49:44

标签: mysql sql

我正在尝试运行查询来获取工作空闲的插槽。 ' 的SQL架构'表格如下:

+------------+----------+------------+----------+
|   workID   | workerID | workerType | workTime |
+------------+----------+------------+----------+
| 0000000001 |        1 | agents     |        1 |
| 0000000002 |        1 | agents     |        2 |
| 0000000003 |        1 | agents     |        4 |
| 0000000004 |        1 | agents     |        4 |
+------------+----------+------------+----------+

另一张表' 工作人员'如:

+----------+------------+
| workerID | workerName |
+----------+------------+
|        1 | John Doe   |
+----------+------------+

我需要输出如下:

+------------+-----------+-----------+-----------+-----------+
| workerType | timeslot1 | timeslot2 | timeslot3 | timeslot4 |
+------------+-----------+-----------+-----------+-----------+
| John Doe   | Occupied  | Occupied  | Free      | Occupied  |
+------------+-----------+-----------+-----------+-----------+

但是根据我的查询,如果我GROUP BY wo.workerID,那么我

+------------+-----------+-----------+-----------+-----------+
| workerName | timeslot1 | timeslot2 | timeslot3 | timeslot4 |
+------------+-----------+-----------+-----------+-----------+
| John Doe   | Free      | Free      | Free      | Occupied  |
+------------+-----------+-----------+-----------+-----------+

我的尝试:

SQLFIDDLE

SELECT wo.workerName,
   CASE
    WHEN w.workTime = 1 THEN 'Occupied'
    ELSE 'Free'
   END AS timeSlot1,
   CASE
    WHEN w.workTime = 2 THEN 'Occupied'
    ELSE 'Free'
   END AS timeSlot2,
   CASE
    WHEN w.workTime = 3 THEN 'Occupied'
    ELSE 'Free'
   END AS timeSlot3,
    CASE
    WHEN w.workTime = 4 THEN 'Occupied'
    ELSE 'Free'
   END AS timeSlot4
FROM works AS w
INNER JOIN workers AS wo ON wo.workerID = w.workerID
WHERE w.workerType = 'agents' AND
  w.workerID = 1
GROUP BY wo.workerID;

3 个答案:

答案 0 :(得分:2)

只需添加max()旋转功能

SELECT wo.workerName,
       max( CASE
        WHEN w.workTime = 1 THEN 'Occupied'
        ELSE 'Free'
       END) AS timeSlot1,
       max(CASE
        WHEN w.workTime = 2 THEN 'Occupied'
        ELSE 'Free'
       END) AS timeSlot2,
       max(CASE
        WHEN w.workTime = 3 THEN 'Occupied'
        ELSE 'Free'
       END) AS timeSlot3,
        max(CASE
        WHEN w.workTime = 4 THEN 'Occupied'
        ELSE 'Free'
       END) AS timeSlot4
FROM works AS w
INNER JOIN workers AS wo ON wo.workerID = w.workerID
WHERE w.workerType = 'agents' AND
      w.workerID = 1

答案 1 :(得分:1)

http://www.sqlfiddle.com/#!9/33230/11

SELECT wo.workerName,
       IF(SUM(IF(w.workTime = 1,1,0)),'Occupied','Free') AS timeSlot1,
       IF(SUM(IF(w.workTime = 2,1,0)),'Occupied','Free') AS timeSlot2,
       IF(SUM(IF(w.workTime = 3,1,0)),'Occupied','Free') AS timeSlot3,
       IF(SUM(IF(w.workTime = 4,1,0)),'Occupied','Free') AS timeSlot4
FROM works AS w
INNER JOIN workers AS wo ON wo.workerID = w.workerID
WHERE w.workerType = 'agents' AND
      w.workerID = 1
GROUP BY w.workerID

答案 2 :(得分:1)

来自@Abhik Chakraborty的答案可能适用于此特定情况,但如果您更改了字符串,例如,占用将变为忙碌,您将从MAX()获得免费。

这是因为MAX()以char-by-char为基础比较字符串。您应该分配一个整数值,然后在其上应用一个函数。

他的方法会失败: 每当Occupied的第一个字符小于Free字符时。例如,将Occupied重命名为Busy

-- How it works right now

 select greatest('occupied','free');
 greatest 
----------
 occupied

-- How the behaviour would change if we rename occupied to free

select greatest('busy','free');
 greatest 
----------
 free

为防止出现这种情况,使用此方法更安全:

SELECT
    workerName, 
    CASE WHEN timeSlot1 = 1 THEN 'Occupied' ELSE 'Free' END AS timeSlot1,
    CASE WHEN timeSlot2 = 1 THEN 'Occupied' ELSE 'Free' END AS timeSlot2,
    CASE WHEN timeSlot3 = 1 THEN 'Occupied' ELSE 'Free' END AS timeSlot3,
    CASE WHEN timeSlot4 = 1 THEN 'Occupied' ELSE 'Free' END AS timeSlot4
FROM(
    SELECT 
        wo.workerName,
        MAX(CASE WHEN w.workTime = '1' THEN 1 END) AS timeSlot1,
        MAX(CASE WHEN w.workTime = '2' THEN 1 END) AS timeSlot2,
        MAX(CASE WHEN w.workTime = '3' THEN 1 END) AS timeSlot3,
        MAX(CASE WHEN w.workTime = '4' THEN 1 END) AS timeSlot4
    FROM                                      
        works AS w
        INNER JOIN workers AS wo ON wo.workerID = w.workerID
    WHERE 
        w.workerType = 'agents' AND
        w.workerID = 1
    GROUP BY wo.workerName
    ) foo;

重要提示

您的workTime列也不应该是varchar(n)的类型。这很容易出错,因为它会按字符比较字符串。

select greatest('211'::varchar, '29'::varchar);
 greatest 
----------
 29

我认为这不是你预期的结果。