The PIVOT
operator was added in Oracle 11gR1. Attempting to run your code in 10gR2 gives your error:
FROM got_r_num PIVOT ( MIN (SAAT) AS s , MIN (HASTA) AS h
*
ERROR at line 15:
ORA-00933: SQL command not properly ended
Prior to 11g you'll need to use a different mechanism, like this one.
I think you want something like this:
WITH got_r_num AS
(
SELECT TO_CHAR (t.r_tarihi, 'DY', 'NLS_DATE_LANGUAGE=ENGLISH') AS gun
, TO_CHAR (t.baslama, 'HH24:MI') AS saat
, h.adi || ' ' || h.soyadi AS hasta
, ROW_NUMBER () OVER ( PARTITION BY TO_CHAR (t.r_tarihi, 'DY')
ORDER BY t.baslama
) AS r_num
FROM randevu_entegre_deneme t
LEFT OUTER JOIN hasta_deneme h ON h.id = t.hasta_id
WHERE (r_tarihi BETWEEN TO_DATE ('20.5.2011', 'dd.mm.yyyy')
AND TO_DATE ('20.5.2011', 'dd.mm.yyyy') + 9)
)
SELECT min(case when gun = 'MON' then SAAT ||' '|| HASTA end) as pazartesi
, min(case when gun = 'TUE' then SAAT ||' '|| HASTA end) as sali
, min(case when gun = 'WED' then SAAT ||' '|| HASTA end) as carsamba
, min(case when gun = 'THU' then SAAT ||' '|| HASTA end) as persembe
, min(case when gun = 'FRI' then SAAT ||' '|| HASTA end) as cuma
FROM got_r_num
GROUP BY r_num
ORDER BY r_num;
With the table and insert statement you posted that gives:
PAZARTESI SALI CARSAMBA PERSEMBE CUMA
-------------------- -------------------- -------------------- -------------------- --------------------
13:00 SEYHAN UNVER 09:45 SEYMA DURLANIK 08:30 ZUHRE YEL 08:54 SEYMA DURLANIK
13:30 SELMA CALISKAN 13:00 TURKAN BICAK 08:48 AYSEL POLAT 10:00 SENGUL AKBAS
17:45 ESMA COMERT 14:00 FATMA ETA 13:30 ORHAN SAVAS
14:00 FATMA ETA
... which doesn't quite match what you said you expected, but does line up with the data and bluefeet's SQl Fiddle using pivot
.
I've used the Turkish day labels you seem to be expecting; as realspirituals pointed out it isn't entirely helpful to change things in your code when you post a question. The language difference is important here as your day comparison is assuming the DY
format is in a certain language - whether you're actually using the English or Turkish abbreviations doesn't matter, the point is you're assuming the client and code are using the same language. You can avoid a potential mismatch there by forcing the DY
to be in a specific language, so you know what you will be comparing against; that's what this is doing, using the optional third parameter to the to_char() function:
TO_CHAR (t.r_tarihi, 'DY', 'NLS_DATE_LANGUAGE=ENGLISH')
Also, I've left it as only reporting five days as you didn't seem interested in weekends. It seems a little odd though that you have a date span of 9 days, since that will include some of those days multiple times, and you won't be able to tell which week a particular time is from. Your r_num
should keep them in order, so you might see the times appearing to not be in the right order if you have them from both weeks, though they will be based on the date too. Presumably that's what you want though.
For the follow-up query about ordering the columns; you can do that by assigning another pseudo-column using dense rank
and using that for the case
instead of gun
:
WITH got_r_num AS
(
SELECT TO_CHAR (t.r_tarihi, 'DY', 'NLS_DATE_LANGUAGE=ENGLISH') AS gun
, TO_CHAR (t.r_tarihi, 'DAY', 'NLS_DATE_LANGUAGE=TURKISH') AS d_name
, DENSE_RANK () OVER ( ORDER BY TRUNC( t.r_tarihi) ) AS d_num
, TO_CHAR (t.baslama, 'HH24:MI') AS saat
, h.adi || ' ' || h.soyadi AS hasta
, ROW_NUMBER () OVER ( PARTITION BY TO_CHAR (t.r_tarihi, 'DY')
ORDER BY t.baslama
) AS r_num
FROM randevu_entegre_deneme t
LEFT OUTER JOIN hasta_deneme h ON h.id = t.hasta_id
WHERE (r_tarihi BETWEEN TO_DATE ('20.5.2011', 'dd.mm.yyyy')
AND TO_DATE ('20.5.2011', 'dd.mm.yyyy') + 9)
)
SELECT min(case when mod(d_num, 7) = 1 then SAAT ||' '|| HASTA end) as day1
, min(case when mod(d_num, 7) = 2 then SAAT ||' '|| HASTA end) as day2
, min(case when mod(d_num, 7) = 3 then SAAT ||' '|| HASTA end) as day3
, min(case when mod(d_num, 7) = 4 then SAAT ||' '|| HASTA end) as day4
, min(case when mod(d_num, 7) = 5 then SAAT ||' '|| HASTA end) as day5
, min(case when mod(d_num, 7) = 6 then SAAT ||' '|| HASTA end) as day6
, min(case when mod(d_num, 7) = 0 then SAAT ||' '|| HASTA end) as day7
FROM got_r_num
GROUP BY r_num
ORDER BY r_num;
DAY1 DAY2 DAY3 DAY4 DAY5 DAY6 DAY7
-------------------- -------------------- -------------------- -------------------- -------------------- -------------------- --------------------
08:54 SEYMA DURLANIK 13:00 SEYHAN UNVER 09:45 SEYMA DURLANIK 08:30 ZUHRE YEL
10:00 SENGUL AKBAS 13:30 SELMA CALISKAN 13:00 TURKAN BICAK 08:48 AYSEL POLAT
13:30 ORHAN SAVAS 17:45 ESMA COMERT 14:00 FATMA ETA
14:00 FATMA ETA
I'm not actually using gun
any more but I've left it in, and added d_name
as the full day name, though neither is currently selected. This is completely skipping what was the carsamba
column because it has no data, which matches what your question showed. That might be what you want if you knew which column was which. Unfortunately you can't dynamically assign the column alias, so you don't know that day1
is actually cuma
. If you want a gap for carsamba
then you can work out the offset of each date from the start date:
, TRUNC( t.r_tarihi) - TO_DATE ('20.5.2011', 'dd.mm.yyyy') + 1 AS d_num
But you still don't know which day column 1 represents. You can fake that but it depends how you're running it. If you are pulling the data from an application then you can query the d_name
as well and use that. From SQL*Plus you could do this if you repeated the query and used substitution variables, which is proabbly a lot of overhead, or a partial solution is just to select them as a separate select, which isn't ideal either:
column r_num noprint
set head off
WITH got_r_num AS
(
...
)
SELECT 0 as r_num
, min(case when mod(d_num, 7) = 1 then d_name end) as day1
, min(case when mod(d_num, 7) = 2 then d_name end) as day2
, min(case when mod(d_num, 7) = 3 then d_name end) as day3
, min(case when mod(d_num, 7) = 4 then d_name end) as day4
, min(case when mod(d_num, 7) = 5 then d_name end) as day5
, min(case when mod(d_num, 7) = 6 then d_name end) as day6
, min(case when mod(d_num, 7) = 0 then d_name end) as day7
FROM got_r_num
UNION ALL
SELECT r_num
, min(case when mod(d_num, 7) = 1 then SAAT ||' '|| HASTA end) as day1
, min(case when mod(d_num, 7) = 2 then SAAT ||' '|| HASTA end) as day2
, min(case when mod(d_num, 7) = 3 then SAAT ||' '|| HASTA end) as day3
, min(case when mod(d_num, 7) = 4 then SAAT ||' '|| HASTA end) as day4
, min(case when mod(d_num, 7) = 5 then SAAT ||' '|| HASTA end) as day5
, min(case when mod(d_num, 7) = 6 then SAAT ||' '|| HASTA end) as day6
, min(case when mod(d_num, 7) = 0 then SAAT ||' '|| HASTA end) as day7
FROM got_r_num
GROUP BY r_num
ORDER BY r_num;
CUMA PAZARTESI SALI PER¿EMBE
08:54 SEYMA DURLANIK 13:00 SEYHAN UNVER 09:45 SEYMA DURLANIK 08:30 ZUHRE YEL
10:00 SENGUL AKBAS 13:30 SELMA CALISKAN 13:00 TURKAN BICAK 08:48 AYSEL POLAT
13:30 ORHAN SAVAS 17:45 ESMA COMERT 14:00 FATMA ETA
14:00 FATMA ETA