2015-04-24 3 views
2

Я пытаюсь запустить запрос, чтобы получить мои слоты, рабочий является бесплатным. 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 | 
+------------+-----------+-----------+-----------+-----------+ 

МОЙ TRY:

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; 
+1

Операции вашего случая не различаются WorkID. Все они смотрят на один и тот же ряд. –

+0

Я так понимаю, даже если рабочий занят в одном заданном рабочем времени через задания, я хочу вернуть его как занятое другое. –

+0

Зачем вам нужно сворачивать данные в РСУБД? Не можете ли вы просто присоединиться к таблицам и повернуть (если это необходимо) в код приложения? – eggyal

ответ

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 
+0

Ничего себе! Работает как шарм. Можете ли вы объяснить, как max() работает для строк? –

+1

Для каждой группы необходимо будет увидеть «max()» и использовать случай, когда мы просто назначаем значение по мере необходимости, чтобы агрегация данных выполнялась с максимальными значениями. –

+0

Проблема в том, что это не сработает, если вы добавили больше агентов или данных. –

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 
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 

Я не думаю, что это ваш ожидаемый результат.

+0

Это хорошо. Однако установка текста в моих руках, и это определенно должно быть показано как занято и бесплатно согласно требованиям. Поэтому ответ Абхика определенно будет выбором №1. Кроме того, мой столбец workTime имеет тип TINYINT (1) –

+0

Из вашего SQLFiddle '' workTime varchar (50) COLLATE utf8_unicode_ci NOT NULL'. Помните, что текст находится в вашей руке, пока он находится в вашей руке. Если вы передадите код кому-либо другому, или любая логика должна быть изменена - может произойти непредвиденное поведение. –

Смежные вопросы