Hope you are doing well..I am trying to convert a plan table as below
Input
Segment | Model |FC1 |FC2 |FC3 |FC4 |FC5 | FC6 | FC7 | FC8 | FC9 | FC10 | FC11 | FC12
HRX P3412 9 14 11 22 17 23 18 15 23 12 12 19
SRX O321 11 8 8 9 9 16 19 7 22 12 11 15
SRX LD12 14 10 20 22 18 19 10 17 21 16 10 21
HRX M421 17 18 16 12 14 17 10 16 8 8 7 23
MRX N342 3 23 16 13 20 9 16 14 16 17 10 11
HRX J231 4 10 20 20 21 23 17 22 14 15 8 22
into the table below based on the current date and the reference table
Segment |Model| Apr-22 |May-22 |Jun-22 |Jul-22 |Aug-22 |Sep-22|Oct-22|Nov-22 | Dec-22 | Jan-23 |Feb-23 |Mar-23
HRX P3412 9 14 11 22 17 23 18 15 23 12 12 19
SRX O321 11 8 8 9 9 16 19 7 22 12 11 15
SRX LD12 14 10 20 22 18 19 10 17 21 16 10 21
HRX M421 17 18 16 12 14 17 10 16 8 8 7 23
MRX N342 3 23 16 13 20 9 16 14 16 17 10 11
HRX J231 4 10 20 20 21 23 17 22 14 15 8 22
Reference table:
Fiscal Month From to
Jan-22 Dec 26 2021 Jan 22 2022
Feb-22 Jan 23 2022 19-Feb-22
Mar-22 20-Feb-22 26-Mar-22
Apr-22 27-Mar-22 23-Apr-22
May-22 24-Apr-22 21-May-22
Jun-22 22-May-22 25-Jun-22
Jul-22 26-Jun-22 23-Jul-22
Aug-22 24-Jul-22 20-Aug-22
Sep-22 21-Aug-22 24-Sep-22
Oct-22 25-Sep-22 22-Oct-22
Nov-22 23-Oct-22 19-Nov-22
Dec-22 20-Nov-22 31-Dec-22
So I need to basically map the column names (FC1,FC2,FC3...input table) to fiscal month based on the current date and looking up the reference table for the fiscal month... Can you please help me here..
The column names should change every fiscal month according to the reference table dynamically ..For example FC1 should be renamed to May 2022 and FC2 should be renamed to June 2022 from 24th April 2022...Similarly from 22nd may 2022 FC1 should be renamed to June 2022, FC2 should be renamed to July 2022...
Please find the DDL for the tables:
create table input
(segment varchar(40),
model varchar (40),
FC1 int,
FC2 int,
FC3 int,
FC4 int,
FC5 int,
FC6 int,
FC7 int,
FC8 int,
FC9 int,
FC10 int,
FC11 int,
FC12 int)
insert into input values
('HRX','P3412','9','14','11','22','17','23','18','15','23','12','12','19'),
('SRX','O321','11','8','8','9','9','16','19','7','22','12','11','15'),
('SRX','LD12','14','10','20','22','18','19','10','17','21','16','10','21'),
('HRX','M421','17','18','16','12','14','17','10','16','8','8','7','23'),
('MRX','N342','3','23','16','13','20','9','16','14','16','17','10','11'),
('HRX','J231','4','10','20','20','21','23','17','22','14','15','8','22')
create table output
(segment varchar(40),
model varchar(40),
Apr2022 int,
May2022 int,
Jun2022 int,
jul2022 int,
aug2022 int,
sep2022 int,
oct2022 int,
nov2022 int,
dec2022 int,
Jan2023 int,
feb2023 int,
mar2023 int)
insert into output values
('HRX','P3412','9','14','11','22','17','23','18','15','23','12','12','19'),
('SRX','O321','11','8','8','9','9','16','19','7','22','12','11','15'),
('SRX','LD12','14','10','20','22','18','19','10','17','21','16','10','21'),
('HRX','M421','17','18','16','12','14','17','10','16','8','8','7','23'),
('MRX','N342','3','23','16','13','20','9','16','14','16','17','10','11'),
('HRX','J231','4','10','20','20','21','23','17','22','14','15','8','22')
create table reference
(fiscalmonth varchar(40),
from date,
to date
)
insert into reference values
('Jan 2022','Dec 26 2021 ','Jan 22 2022'),
('Feb 2022','Jan 23 2022','Feb 19 2022'),
('March 2022','feb 20 2022','Mar 26 2022'),
('April 2022','Mar 27 2022','Apr 23 2022'),
('May 2022','Apr 24 2022','May 21 2022'),
('June 2022','May 22 2022','Jun 25 2022'),
('July 2022','June 26 2022','Jul 23 2022'),
('Aug 2022','Jul 24 2022','Aug 20 2022'),
('Sep 2022','Aug 21 2022','Sep 24 2022'),
('Oct 2022','Sep 25 2022','Oct 22 2022'),
('Nov 2022','Oct 23 2022','Nov 19 2022'),
('Dec 2022','Nov 20 2022','Dec 31 2022')
We can fetch the first 12 rows starting with the current month, and number them using row_number. We then do a manual pivot, using rn so that it will not need changing from month to month.
The only thing that will need to be kept up to date is the references table. (I have added some months for 2023 using the same dates as 2022.
select
'' segment,
'' model,
max(case when rn = 1 then fiscalmonth end) FC1,
max(case when rn = 2 then fiscalmonth end) FC2,
max(case when rn = 3 then fiscalmonth end) FC3,
max(case when rn = 4 then fiscalmonth end) FC4,
max(case when rn = 5 then fiscalmonth end) FC5,
max(case when rn = 6 then fiscalmonth end) FC6,
max(case when rn = 7 then fiscalmonth end) FC7,
max(case when rn = 8 then fiscalmonth end) FC8,
max(case when rn = 9 then fiscalmonth end) FC9,
max(case when rn = 10 then fiscalmonth end) FC10,
max(case when rn = 11 then fiscalmonth end) FC11,
max(case when rn = 12 then fiscalmonth end) FC12
from
(select
row_number() over (order by to_ ) as rn,
fiscalmonth from reference
where to_ >= curdate()
limit 12) as months
union all
select * from input
segment | model | FC1 | FC2 | FC3 | FC4 | FC5 | FC6 | FC7 | FC8 | FC9 | FC10 | FC11 | FC12
:------ | :---- | :--------- | :------- | :-------- | :-------- | :------- | :------- | :------- | :------- | :------- | :------- | :------- | :---------
| | April 2022 | May 2022 | June 2022 | July 2022 | Aug 2022 | Sep 2022 | Oct 2022 | Nov 2022 | Dec 2022 | Jan 2023 | Feb 2023 | March 2023
HRX | P3412 | 9 | 14 | 11 | 22 | 17 | 23 | 18 | 15 | 23 | 12 | 12 | 19
SRX | O321 | 11 | 8 | 8 | 9 | 9 | 16 | 19 | 7 | 22 | 12 | 11 | 15
SRX | LD12 | 14 | 10 | 20 | 22 | 18 | 19 | 10 | 17 | 21 | 16 | 10 | 21
HRX | M421 | 17 | 18 | 16 | 12 | 14 | 17 | 10 | 16 | 8 | 8 | 7 | 23
MRX | N342 | 3 | 23 | 16 | 13 | 20 | 9 | 16 | 14 | 16 | 17 | 10 | 11
HRX | J231 | 4 | 10 | 20 | 20 | 21 | 23 | 17 | 22 | 14 | 15 | 8 | 22
db<>fiddle here
I'm am having difficulty in trying to make this work. I have the following table that has patients stay in a hospital. They each have an admission date and a discharge date, each stay has an episode id. For the life of me, I can not figure out how to query the table to work out if the patient has been discharged and been readmitted within 28 days of the previous stay. Any pointers would be appreciated.
ID
Admission
Discharge
EpisodeID
PatientID
01
2020-02-17
2020-03-10
1234
1
02
2020-02-18
2020-03-15
1235
2
03
2020-02-20
2020-03-19
1236
3
04
2020-03-17
2020-03-30
1237
1
05
2020-03-19
2020-03-25
1238
4
06
2020-03-22
2020-03-29
1239
5
07
2020-03-29
2020-04-03
1240
6
08
2020-03-30
2020-04-10
1241
2
09
2020-04-01
1242
7
10
2020-04-17
1243
2
Output
ID
Admission
Discharge
EpisodeID
PatientID
Readmit
01
2020-02-17
2020-03-10
1234
1
N
02
2020-02-18
2020-03-15
1235
2
N
03
2020-02-20
2020-03-19
1236
3
N
04
2020-03-17
2020-03-30
1237
1
Y
05
2020-03-19
2020-03-25
1238
4
N
06
2020-03-22
2020-03-29
1239
5
N
07
2020-03-29
2020-04-03
1240
6
N
08
2020-03-30
2020-04-10
1241
2
Y
09
2020-04-01
1242
7
N
10
2020-04-17
1243
2
Y
You can use simple LEFT JOIN in this case:
SELECT
p.*,
IF(prev.PatientID IS NOT NULL, 'Y', 'N') Readmit
FROM p
LEFT JOIN p prev ON
p.PatientID = prev.PatientID AND
DATEDIFF(p.Admission, prev.Discharge) BETWEEN 1 AND 28 ;
Look MySQL online fiddle
Thanks to Slava I was able to get what I needed. If anyone else comes across this, here is the solution that I used; (If I have made any mistakes I apologize)
CREATE TABLE p (ID int, Admission date, Discharge date, EpisodeID int, PatientID int);
INSERT INTO p VALUES
('01', '2020-02-17', '2020-03-10', 1234, 1),
('02', '2020-02-18', '2020-03-15', 1235, 2),
('03', '2020-02-20', '2020-03-19', 1236, 3),
('04', '2020-03-17', '2020-03-30', 1237, 1),
('05', '2020-03-19', '2020-03-25', 1238, 4),
('06', '2020-03-22', '2020-03-29', 1239, 5),
('07', '2020-03-29', '2020-04-03', 1240, 6),
('08', '2020-03-30', '2020-04-10', 1241, 2),
('09', '2020-04-01', null, 1242, 7),
('10', '2020-04-17', '2020-04-18', 1243, 2),
('11', '2020-04-17', null, 1244, 2);
SELECT
p.*,
IF(DATEDIFF(p.Admission, prev.Discharge)<29,'Y','N') Readmit,
DATEDIFF(p.Admission, prev.Discharge) Days_Between
FROM p
LEFT JOIN p prev ON p.PatientID = prev.PatientID
AND DATEDIFF(p.Admission, prev.Discharge) BETWEEN 1 AND 28 ;
+====+============+============+===========+===========+=========+==============+
| ID | Admission | Discharge | EpisodeID | PatientID | Readmit | Days_Between |
+====+============+============+===========+===========+=========+==============+
| 1 | 2020-02-17 | 2020-03-10 | 1234 | 1 | N | (null) |
+----+------------+------------+-----------+-----------+---------+--------------+
| 2 | 2020-02-18 | 2020-03-15 | 1235 | 2 | N | (null) |
+----+------------+------------+-----------+-----------+---------+--------------+
| 3 | 2020-02-20 | 2020-03-19 | 1236 | 3 | N | (null) |
+----+------------+------------+-----------+-----------+---------+--------------+
| 4 | 2020-03-17 | 2020-03-30 | 1237 | 1 | Y | 20 |
+----+------------+------------+-----------+-----------+---------+--------------+
| 5 | 2020-03-19 | 2020-03-25 | 1238 | 4 | N | (null) |
+----+------------+------------+-----------+-----------+---------+--------------+
| 6 | 2020-03-22 | 2020-03-29 | 1239 | 5 | N | (null) |
+----+------------+------------+-----------+-----------+---------+--------------+
| 7 | 2020-03-29 | 2020-04-03 | 1240 | 6 | N | (null) |
+----+------------+------------+-----------+-----------+---------+--------------+
| 8 | 2020-03-30 | 2020-04-10 | 1241 | 2 | Y | 26 |
+----+------------+------------+-----------+-----------+---------+--------------+
| 9 | 2020-04-01 | (null) | 1242 | 7 | N | (null) |
+----+------------+------------+-----------+-----------+---------+--------------+
| 10 | 2020-04-17 | 2020-04-18 | 1243 | 2 | Y | 8 |
+----+------------+------------+-----------+-----------+---------+--------------+
| 11 | 2020-04-17 | (null) | 1244 | 2 | N | 382 |
+----+------------+------------+-----------+-----------+---------+--------------+
SQLize
I have the following query:
SELECT from_unixtime(table1.eventTime, '%Y %D %M') AS DAY, table1.ID, table1.eventTime, COUNT(*)
FROM table1 table1
GROUP BY from_unixtime(table1.eventTime, '%Y %D %M'), table1.ID, table1.eventTime
This is giving me the following output:
DAY ID eventTime COUNT(*)
2017 10th November 815 1510275600 1
2017 10th November 902 1510275600 1
2017 10th November 1202 1510275600 1
2017 10th November 1202 1510279200 1
2017 10th November 1202 1510282800 1
2017 10th November 1202 1510286400 1
2017 10th November 1342 1510275600 1
2017 10th November 1404 1510275600 1
2017 10th November 1404 1510275600 1
How can i achieve this?
DAY ID eventTime COUNT(*)
2017 10th November 815 1510275600 1
2017 10th November 902 1510275600 1
2017 10th November 1202 1510275600 1
2017 10th November 1202 1510279200 2
2017 10th November 1202 1510282800 3
2017 10th November 1202 1510286400 4
2017 10th November 1342 1510275600 1
2017 10th November 1404 1510275600 1
2017 10th November 1404 1510275600 2
In fact what i need is to group by day and based on the eventTime to make a numbering where the ID is same.
You are basically after mysql row number simulation. There are loads of examples in SO and here's another
drop table if exists t;
create table t
(Dt date, ID int ,eventtime int);
insert into t values
('2017-11-10' ,815 ,1510275600),
('2017-11-10' ,902 ,1510275600),
('2017-11-10' ,1202 ,1510275600),
('2017-11-10' ,1202 ,1510279200),
('2017-11-10' ,1202 ,1510282800),
('2017-11-10' ,1202 ,1510286400),
('2017-11-10' ,1342 ,1510275600),
('2017-11-10' ,1404 ,1510275600),
('2017-11-10' ,1404 ,1510275600);
select dt,id,eventtime,
if(id <> #p,#rn:=1,#rn:=#rn+1) rownumber,
#p:=id p
from t , (select #rn:=0,#p:=0) r
order by id,dt,eventtime
result
+------------+------+------------+-----------+------+
| dt | id | eventtime | rownumber | p |
+------------+------+------------+-----------+------+
| 2017-11-10 | 815 | 1510275600 | 1 | 815 |
| 2017-11-10 | 902 | 1510275600 | 1 | 902 |
| 2017-11-10 | 1202 | 1510275600 | 1 | 1202 |
| 2017-11-10 | 1202 | 1510279200 | 2 | 1202 |
| 2017-11-10 | 1202 | 1510282800 | 3 | 1202 |
| 2017-11-10 | 1202 | 1510286400 | 4 | 1202 |
| 2017-11-10 | 1342 | 1510275600 | 1 | 1342 |
| 2017-11-10 | 1404 | 1510275600 | 1 | 1404 |
| 2017-11-10 | 1404 | 1510275600 | 2 | 1404 |
+------------+------+------------+-----------+------+
9 rows in set (0.00 sec)
I have the following data in my webinar_timing table in mysql database
start_time and end_time are of type datetime
id | webinar_id | start_time | end_time
-------------------------------------------------------------------
1 | 5 | 3/18/2015 6:00:00 PM | 3/18/2015 7:00:00 PM
2 | 5 | 3/19/2015 6:00:00 PM | 3/19/2015 7:00:00 PM
3 | 5 | 3/20/2015 6:00:00 PM | 3/20/2015 7:00:00 PM
4 | 5 | 3/21/2015 6:00:00 PM | 3/21/2015 7:00:00 PM
5 | 5 | 3/22/2015 6:00:00 PM | 3/22/2015 7:00:00 PM
6 | 11 | 3/20/2015 8:00:00 PM | 3/20/2015 9:00:00 PM
7 | 11 | 3/21/2015 8:00:00 PM | 3/21/2015 9:00:00 PM
8 | 11 | 3/22/2015 8:00:00 PM | 3/22/2015 9:00:00 PM
9 | 22 | 3/25/2015 8:00:00 PM | 3/25/2015 9:00:00 PM
10 | 22 | 3/27/2015 8:00:00 PM | 3/27/2015 9:00:00 PM
11 | 22 | 3/29/2015 8:00:00 PM | 3/27/2015 9:00:00 PM
Basically, for each webinar, I want the total occurences and number of classes completed or remaining AND the NEXT upcoming class
Egs: When I run this query say at 3/21/2015 at 4:00 PM - this is the result I am expecting
webinar_id | total | Classes Completed | Next Class
----------------------------------------------------------
5 | 5 | 3 | 3/21/2015 6:00:00 PM
11 | 3 | 1 | 3/21/2015 8:00:00 PM
22 | 3 | 0 | 3/25/2015 8:00:00 PM
OR
webinar_id | total | Classes Remaining | Next Class
----------------------------------------------------------
5 | 5 | 2 | 3/21/2015 6:00:00 PM
11 | 3 | 2 | 3/21/2015 8:00:00 PM
22 | 3 | 3 | 3/25/2015 8:00:00 PM
Based on a previous question - a fellow SO Peter assisted with the following
select webinar_id, count(*) AS total,
SUM(IF(end_time<NOW(), 1, 0)) AS completed,
SUM(IF(start_time>=NOW(), 1, 0)) AS remaining
from webinar_times
group by webinar_id;
SQL Fiddle
http://sqlfiddle.com/#!9/c4e71/1
Any help will be appreciated
Thanks in advance
Something like:
select webinar_id
, count(*) AS total
, count(case when end_time<NOW() then 1 end) as completed
, (select count(1)
from webinar_times y
where x.webinar_id = y.webinar_id
and y.start_time > NOW()) as remaining
, min(case when x.start_time > NOW() then x.start_time end) as next_class
from webinar_times x
group by webinar_id;
should do
EDIT: realized that the sub-select is un-necessary:
select webinar_id
, count(*) AS total
, count(case when end_time<NOW() then 1 end) as completed
, count(case when start_time>NOW() then 1 end) as remaining
, min(case when x.start_time > NOW() then x.start_time end) as next_class
from webinar_times x
group by webinar_id;
You can make an outer join between two grouped queries, e.g. one that counts the total number of webinars and another that both counts the remaining webinars and obtains the start time of the next one:
SELECT * FROM (
SELECT webinar_id, COUNT(*) total
FROM webinar_times
GROUP BY webinar_id
) totals NATURAL LEFT JOIN (
SELECT webinar_id, COUNT(*) remaining, MIN(start_time) next
FROM webinar_times
WHERE start_time > NOW()
GROUP BY webinar_id
) future
See it on sqlfiddle:
+------------+-------+-----------+-------------------------+
| webinar_id | total | remaining | next |
+------------+-------+-----------+-------------------------+
| 6 | 5 | 1 | March, 22 2015 06:00:00 |
| 11 | 3 | 1 | March, 22 2015 07:00:00 |
| 22 | 3 | 3 | March, 25 2015 07:00:00 |
+------------+-------+-----------+-------------------------+
A composite index defined over (webinar_id, start_time) would benefit this query, and avoids the full table scans that the approach outlined in your question would otherwise require.
Consider the following example and this will give you what you need
mysql> create table test (id int, webinar_id int, start_time datetime);
Query OK, 0 rows affected (0.16 sec)
mysql> insert into test values (1,5,'2015-03-18 18:00:00'),
(2,5,'2015-03-19 18:00:00'),
(3,5,'2015-03-20 18:00:00'),
(4,5,'2015-03-21 18:00:00'),
(5,5,'2015-03-21 18:00:00'),
(6,11,'2015-03-20 20:00:00'),
(7,11,'2015-03-21 20:00:00'),
(8,11,'2015-03-22 20:00:00'),
(9,22,'2015-03-25 20:00:00'),
(10,22,'2015-03-27 20:00:00'),
(11,22,'2015-03-29 20:00:00');
Query OK, 11 rows affected (0.05 sec)
Records: 11 Duplicates: 0 Warnings: 0
mysql> select * from test ;
+------+------------+---------------------+
| id | webinar_id | start_time |
+------+------------+---------------------+
| 1 | 5 | 2015-03-18 18:00:00 |
| 2 | 5 | 2015-03-19 18:00:00 |
| 3 | 5 | 2015-03-20 18:00:00 |
| 4 | 5 | 2015-03-21 18:00:00 |
| 5 | 5 | 2015-03-21 18:00:00 |
| 6 | 11 | 2015-03-20 20:00:00 |
| 7 | 11 | 2015-03-21 20:00:00 |
| 8 | 11 | 2015-03-22 20:00:00 |
| 9 | 22 | 2015-03-25 20:00:00 |
| 10 | 22 | 2015-03-27 20:00:00 |
| 11 | 22 | 2015-03-29 20:00:00 |
+------+------------+---------------------+
11 rows in set (0.00 sec)
select
t.webinar_id,
count(*) as total,
sum( case when t.start_time < now() then 1 else 0 end) as completed ,
sum( case when t.start_time > now() then 1 else 0 end) as remaining,
t1.next_date from test t
join (
select
webinar_id,
min(start_time) as next_date
from test where start_time > now()
group by webinar_id
)t1 on t.webinar_id= t1.webinar_id
group by t.webinar_id;
+------------+-------+-----------+-----------+---------------------+
| webinar_id | total | completed | remaining | next_date |
+------------+-------+-----------+-----------+---------------------+
| 5 | 5 | 3 | 2 | 2015-03-21 18:00:00 |
| 11 | 3 | 1 | 2 | 2015-03-21 20:00:00 |
| 22 | 3 | 0 | 3 | 2015-03-25 20:00:00 |
+------------+-------+-----------+-----------+---------------------+
3 rows in set (0.00 sec)