简体   繁体   中英

What is the correct syntax for partitioning in SQL

I have a table PatientAppointment . There is only 2 columns AppointmentDateTime and Duration which stores date and total hr or minutes for which that particular patient had his appointment. Let us assume there is only one patient for now. I'm facing issues with partitioning. Here is the table:

+---------------------+-----------------+
| AppointmentDateTime | Duration        |
+---------------------+-----------------+
| 2020-05-28          |   30 min        |
| 2020-05-29          |   30 min        |
| 2020-05-30          |   1 hour        |
| 2020-06-03          |   1 hour        |
| 2020-06-05          |   1 hour 30 min |
| 2020-07-21          |   1 hour 30 min |
| 2020-07-22          |   1 hour        |
| 2020-07-28          |   30 min        |
+---------------------+-----------------+

Here is the query. I'm first converting duration to minutes in integer like 30, 60, 90 so that I can sum them up. Then I've to partition them month wise. It should look like db<>fiddle . This works on fiddle.

select 
sum(((case when duration like '% hour%' then substring_index(duration, ' hour', 1) * 60 else 0 end) +
(case when duration like '%min%' then substring_index(substring_index(duration, ' min', 1), ' ', -1) + 0 else 0 end))) over (partition by date_format(pa.AppointmentDateTime, '%Y-%m') order by pa.AppointmentDateTime) total
from PatientAppointment pa

This works on fiddle. But gives error on my local:

Error Code: 1064. You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(partition by date_format(pa.AppointmentDateTime, '%Y-%m') order by pa.Appointme' at line 3

My local version are:

innodb_version 5.7.26, protocol_version 10, tls_version TLSv1,TLSv1.1,TLSv1.2 version 5.7.26-log

Please help me what to do now.

Cumulative sum using UDV:

select
dateOfCheckup,
duration,

-- use intermediate variable @cur_dur for not calculate this value twice
@cur_dur := ((case when duration like '% hour%' then substring_index(duration, ' hour', 1) * 60 else 0 end) +
(case when duration like '%min%' then substring_index(substring_index(duration, ' min', 1), ' ', -1) + 0 else 0 end)) as minutes,

-- check does current @year_month is equal to previous, continue or restart @cum_sum
CASE WHEN @year_month = date_format(dateOfCheckup, '%Y-%m')
     THEN @cum_sum := @cum_sum + @cur_dur
     ELSE @cum_sum := @cur_dur
     END total,

-- store current @year_month for to use with next row
@year_month := date_format(dateOfCheckup, '%Y-%m') monthOfCheckup

from patient, 

-- initialize variables which will be used
(SELECT @year_month:='', @cum_sum:=0, @cur_dur:=0) variables

-- the rows must be processed in definite order
ORDER BY dateOfCheckup

fiddle

Output columns order is critical (the calulations in output columns in a row are performed strictly in the order in which they're written). But it doesn't matter if this example is used as a subquery or the output data is accessed by column names.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM