I am trying to run a query to fetch me slots a worker is free. The SQL Schema for ' works ' table is as follows:
+------------+----------+------------+----------+
| workID | workerID | workerType | workTime |
+------------+----------+------------+----------+
| 0000000001 | 1 | agents | 1 |
| 0000000002 | 1 | agents | 2 |
| 0000000003 | 1 | agents | 4 |
| 0000000004 | 1 | agents | 4 |
+------------+----------+------------+----------+
Another table ' worker ' is as:
+----------+------------+
| workerID | workerName |
+----------+------------+
| 1 | John Doe |
+----------+------------+
I need the output as follows:
+------------+-----------+-----------+-----------+-----------+
| workerType | timeslot1 | timeslot2 | timeslot3 | timeslot4 |
+------------+-----------+-----------+-----------+-----------+
| John Doe | Occupied | Occupied | Free | Occupied |
+------------+-----------+-----------+-----------+-----------+
But by my query, if I GROUP BY wo.workerID
then I get
+------------+-----------+-----------+-----------+-----------+
| workerName | timeslot1 | timeslot2 | timeslot3 | timeslot4 |
+------------+-----------+-----------+-----------+-----------+
| John Doe | Free | Free | Free | Occupied |
+------------+-----------+-----------+-----------+-----------+
MY TRY:
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;
Just add max()
function for pivoting
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
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
Answer from @Abhik Chakraborty
may be working for this particular case, but if you ever change the strings for example Occupied will become Busy you are going to get Free as a result from MAX()
.
This is because MAX()
compares strings on a char-by-char basis. You should assign an integer value and then apply a function on it.
His method would fail: Whenever Occupied
's first character would be smaller than Free
character. For example rename Occupied
to 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
To prevent this case it is safer to use this method:
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;
Important Note
Your workTime
column should not be type of varchar(n)
as well. This is error prone because it compares strings by characters.
select greatest('211'::varchar, '29'::varchar);
greatest
----------
29
I don't think it would be your expected result.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.