how to get location based on multiple conditions in sql server - sql-server-2008

How can I get my desired output based on two tables in sql server:
CREATE TABLE [dbo].[Goal](
[Location] [varchar](50) NULL,
[Goal] [int] NULL,
[Month] [date] NULL
)
CREATE TABLE [dbo].[Master](
[Date] [date] NULL,
[Employee] [varchar](50) NULL,
[GP] [int] NULL,
[Location] [varchar](50) NULL
)
INSERT [dbo].[Goal] ([Location], [Goal], [Month]) VALUES (N'MG Road', 50000, CAST(0xB93D0B00 AS Date))
GO
INSERT [dbo].[Goal] ([Location], [Goal], [Month]) VALUES (N'Madiwala', 60000, CAST(0xB93D0B00 AS Date))
GO
INSERT [dbo].[Goal] ([Location], [Goal], [Month]) VALUES (N'Silk Board', 30000, CAST(0xB93D0B00 AS Date))
GO
INSERT [dbo].[Goal] ([Location], [Goal], [Month]) VALUES (N'BTM', 35000, CAST(0xB93D0B00 AS Date))
GO
INSERT [dbo].[Goal] ([Location], [Goal], [Month]) VALUES (N'MG Road', 55000, CAST(0xBA3D0B00 AS Date))
GO
INSERT [dbo].[Goal] ([Location], [Goal], [Month]) VALUES (N'Madiwala', 65000, CAST(0xBA3D0B00 AS Date))
GO
INSERT [dbo].[Goal] ([Location], [Goal], [Month]) VALUES (N'Silk Board', 35000, CAST(0xBA3D0B00 AS Date))
GO
INSERT [dbo].[Goal] ([Location], [Goal], [Month]) VALUES (N'BTM', 35000, CAST(0xBA3D0B00 AS Date))
GO
INSERT [dbo].[Master] ([Date], [Employee], [GP], [Location]) VALUES (CAST(0x283E0B00 AS Date), N'Ram', 2000, N'MG Road')
GO
INSERT [dbo].[Master] ([Date], [Employee], [GP], [Location]) VALUES (CAST(0x283E0B00 AS Date), N'Ram', 1800, N'Silk Board')
GO
INSERT [dbo].[Master] ([Date], [Employee], [GP], [Location]) VALUES (CAST(0x293E0B00 AS Date), N'Sami', 15000, N'BTM')
GO
INSERT [dbo].[Master] ([Date], [Employee], [GP], [Location]) VALUES (CAST(0x2A3E0B00 AS Date), N'Ram', 2500, N'Silk Board')
GO
INSERT [dbo].[Master] ([Date], [Employee], [GP], [Location]) VALUES (CAST(0x2A3E0B00 AS Date), N'Ram', 2500, N'MG Road')
GO
INSERT [dbo].[Master] ([Date], [Employee], [GP], [Location]) VALUES (CAST(0x293E0B00 AS Date), N'Sami', 2000, N'BTM')
GO
INSERT [dbo].[Master] ([Date], [Employee], [GP], [Location]) VALUES (CAST(0x2A3E0B00 AS Date), N'Sami', 19000, N'Madiwala')
GO
INSERT [dbo].[Master] ([Date], [Employee], [GP], [Location]) VALUES (CAST(0x2E3E0B00 AS Date), N'Ram', 30000, N'MG Road')
GO
INSERT [dbo].[Master] ([Date], [Employee], [GP], [Location]) VALUES (CAST(0x2E3E0B00 AS Date), N'Ram', 30000, N'Madiwala')
GO
INSERT [dbo].[Master] ([Date], [Employee], [GP], [Location]) VALUES (CAST(0x2F3E0B00 AS Date), N'Ram', 25000, N'Madiwala')
GO
INSERT [dbo].[Master] ([Date], [Employee], [GP], [Location]) VALUES (CAST(0x2E3E0B00 AS Date), N'Sami', 20000, N'BTM')
GO
INSERT [dbo].[Master] ([Date], [Employee], [GP], [Location]) VALUES (CAST(0x2E3E0B00 AS Date), N'Sami', 15000, N'Silk Board')
GO
INSERT [dbo].[Master] ([Date], [Employee], [GP], [Location]) VALUES (CAST(0x2F3E0B00 AS Date), N'Sami', 15000, N'Silk Board')
based on above data I want output like below :
Employe |Location |TotalGP|Month Goal |Goal %
Ram |MG Road |3800 |50000 |7.6
Ram |MG Road |5000 |50000 |10
Ram |Madiwala |60000 |65000 |92.30769231
Sami |Madiwala |17000 |60000 |28.33333333
Sami |Madiwala |19000 |60000 |31.66666667
Sami |Silk board |35000 |35000 |100
sami |Silk board |15000 |35000 |42.85714286
Ram |Madiwala |25000 |65000 |38.46153846
I tried this:
select employee,date,sum(gp)totalgp
from master
group by employee,date
select * from
(select date,employee,location,gp,ROW_NUMBER() over (partition by employee,date order by gp desc ) as rn
from master
) a
where rn=1
above query not given expected result.
Goal %: totalgp/monthgoal * 100
Month Goal:Month goal should be selected from the month goal table, and it should displaying the goal of the location in which the employee has yielded maximum GP (sum of GP) in a
eg : Ram worked in both MG Road and madiwala, but his sum of GP is more in MG Road so MG road'Goal is diplayed against Ram for April month , but for May month Ram's Goal
Total GP definition:
Eg Ram on 25-04-18 has gained 2000 only in MG road , but in other location on same day he has gained 1800 extra , so we are displaying 3800 for Ram irrespective to the location
Location column definition
Location - The employee might work in one or two locations , but here you should display the location in which he has scored maximum Gp (total Gp of the month in a
eg : Ram worked in both MG Road and madiwala, but his sum of GP is more in MG Road so MG road is diplayed for April month , but for May month Ram locaion is madiwala

Use this query
select date,employee,sum(gp)as totalgp,max(goal) as monthgoal,cast(sum(gp)* 100.0/max(goal) as float) as 'Goal%'
from goal
inner join master on master.location=goal.location
where month(goal.month)=month(master.date)
group by date,employee
The output is like this
date employee totalgp monthgoal Goal%
---------- -------------------------------------------------- ----------- ----------- ----------------------
2018-04-25 Ram 3800 50000 7.6
2018-04-26 Sami 17000 35000 48.571428571428
2018-04-27 Ram 5000 50000 10
2018-04-27 Sami 19000 60000 31.666666666666
2018-05-01 Ram 60000 65000 92.307692307692
2018-05-01 Sami 35000 35000 100
2018-05-02 Ram 25000 65000 38.461538461538
2018-05-02 Sami 15000 35000 42.857142857142
Note :
You have to make the date format same for both the tables

Related

Calculate the period of validity of the price

I have a table with an item, its cost and the date it was added.
CREATE TABLE item_prices (
item_id INT,
item_name VARCHAR(30),
item_price DECIMAL(12, 2),
created_dttm DATETIME
);
INSERT INTO item_prices(item_id, item_name, item_price, created_dttm) VALUES
(1, 'spoon', 10.20 , '2023-01-01 01:00:00'),
(1, 'spoon', 10.20 , '2023-01-08 01:35:00'),
(1, 'spoon', 10.35 , '2023-01-14 15:00:00'),
(2, 'table', 40.00 , '2023-01-01 01:00:00'),
(2, 'table', 40.00 , '2023-01-03 11:22:00'),
(2, 'table', 41.00 , '2023-01-10 08:28:22'),
(1, 'spoon', 10.35 , '2023-01-28 21:52:00'),
(1, 'spoon', 11.00 , '2023-02-15 16:36:00'),
(2, 'table', 41.00 , '2023-02-16 21:42:11'),
(2, 'table', 45.20 , '2023-02-19 20:25:25'),
(1, 'spoon', 9.00 , '2023-03-02 14:50:00'),
(1, 'spoon', 9.00 , '2023-03-06 16:36:00'),
(1, 'spoon', 8.50 , '2023-03-15 12:00:00'),
(2, 'table', 30 , '2023-03-05 10:10:10'),
(2, 'table', 30 , '2023-03-10 15:45:00');
I need to create a new table with the following fields:
"item_id",
"item_name",
"item_price",
"valid_from_dt": date on which the price was effective (created_dttm price record)
"valid_to_dt": date until which this price was valid (created_dttm of the next record for this product "minus" one day)
I thought it might be possible to start by selecting days on which new entries are added with new prices with such a request:
SELECT item_id, item_name, item_price,
MIN(created_dttm) as dt
FROM table
GROUP BY item_price, item_id, item_name
that provides me this output:
The expected output is the following:
item_id
item_name
item_price
valid_from_dt
valid_to_dt
1
spoon
10.20
2023-01-01
2023-01-13
1
spoon
10.35
2023-01-14
2023-02-14
1
spoon
11.00
2023-02-15
2023-03-01
1
spoon
9.00
2023-03-02
2023-03-01
1
spoon
8.50
2023-03-15
2023-03-14
2
table
40.00
2023-01-01
2022-01-09
2
table
41.00
2023-01-10
2023-02-18
....
....
....
....
....
select distinct
item_id,
item_name,
first_value(item_price) over (partition by item_id order by created_dttm) as item_price,
min(created_dttm) over (partition by item_id ) as valid_from_dt,
max(created_dttm) over (partition by item_id ) as valid_to_dt
from item_prices
;
output:
item_id
item_name
item_price
valid_from_dt
valid_to_dt
1
spoon
10.20
2023-01-01 01:00:00
2023-03-15 12:00:00
2
table
40.00
2023-01-01 01:00:00
2023-03-10 15:45:00
see: DBFIDDLE
Your query is correct. It's only missing the next step:
retrieving the next "valid_from_dt" in the partition <item_id, item_name>, using the LEAD function
subtract 1 day from it
WITH cte AS (
SELECT item_id, item_name, item_price,
MIN(created_dttm) AS valid_from_dt
FROM item_prices
GROUP BY item_id, item_name, item_price
)
SELECT *,
LEAD(valid_from_dt) OVER(PARTITION BY item_id, item_name) - INTERVAL 1 DAY AS valid_to_dt
FROM cte
Check the demo here.

MySQL case query only getting one result

EDITED: I am trying to CASE a query from my table when a result meets 2 sets of criteria (Flight Time & Tail Number), but I am receiving the wrong result. I only started SQL a few weeks ago for an upcoming school assignment, but am having trouble with this query.
SELECT FlightNumber AS 'Flight Number', Date, Aircraft, Aircraft_Manufacturer AS 'Aircraft Manufacturer', Tail_Number AS 'Tail Number', Departure, Arrival, FlightTime AS 'Flight Time', Instructor, Passengers,
CASE
WHEN SUM(FlightTime) >= 20 AND Tail_Number LIKE '24-%' THEN "RAAus Recreational Pilots Certificate (RPC)"
WHEN SUM(FlightTime) >= 25 AND Tail_Number LIKE '24-%' THEN "RAAus RPC Passenger Endorsment"
WHEN SUM(FlightTime) >= 32 AND Tail_Number LIKE '24-%' THEN "RAAus RPC Cross Country Endorsment"
WHEN SUM(FlightTime) >= 7 AND Tail_Number LIKE 'VH-%' THEN "RPC Conversion to CASA Recreational Pilot License (RPL)"
ELSE 'Not Eligible For License'
END AS "License Eligibility"
FROM Flight_Log
GROUP BY FlightNumber
ORDER BY FlightNumber
My results are:
Expected Results:
Flight Number
Flight Time
Licence Eligibility
1
7
Not Eligible for License
2
6
Not Eligible for License
3
8
Not Eligible for License
4
5
RAAus Recreational Pilots Certificate (RPC)
Once the cumulative hours reaches 20 or more to show the WHEN statements.
My Table Creation with the INSERT INTO looks like this for anyone wondering (I have removed a few rows from the end):
CREATE TABLE IF NOT EXISTS Flight_Log (
`FlightNumber` INTEGER PRIMARY KEY AUTO_INCREMENT,
`Date` DATE,
`Aircraft` VARCHAR(50),
`Aircraft_Manufacturer` VARCHAR(50),
`Tail_Number` VARCHAR(50),
`MTOW` INTEGER,
`Manufacture_Year` YEAR,
`Aircraft_Type` VARCHAR(50),
`Departure` CHAR(4),
`Arrival` CHAR(4),
`FlightTime` INTEGER,
`Instructor` BOOLEAN,
`Passengers` INTEGER
);
INSERT INTO Flight_Log VALUES (1,'2022-10-08','Tecnam P-92 Eaglet','Tecnam','24-5955',600,1992,'Recreational','YCDR','YCDR',1,'1',0);
INSERT INTO Flight_Log VALUES (2,'2022-12-03','Tecnam P-92 Eaglet','Tecnam','24-5955',600,1992,'Recreational','YCDR','YCDR',3,'1',0);
INSERT INTO Flight_Log VALUES (3,'2022-12-05','Tecnam P-92 Eaglet','Tecnam','24-5955',600,1992,'Recreational','YCDR','YCDR',3,'1',0);
INSERT INTO Flight_Log VALUES (4,'2022-12-08','Tecnam Sierra','Tecnam','24-7155',600,2002,'Recreational','YCDR','YCDR',3,'1',0);
INSERT INTO Flight_Log VALUES (5,'2022-12-17','Tecnam Sierra','Tecnam','24-7155',600,2002,'Recreational','YCDR','YCDR',3,'1',0);
INSERT INTO Flight_Log VALUES (6,'2022-12-27','Fly Synthesis Texan','Fly Synthesis','24-5285',600,1998,'Recreational','YCDR','YCDR',1,'1',0);
INSERT INTO Flight_Log VALUES (7,'2022-12-31','Tecnam Sierra','Tecnam','24-7155',600,2002,'Recreational','YCDR','YCDR',2,'0',0);
INSERT INTO Flight_Log VALUES (8,'2023-01-01','Tecnam P-92 Eaglet','Tecnam','24-5955',600,1992,'Recreational','YCDR','YCDR',2,'0',0);
INSERT INTO Flight_Log VALUES (9,'2023-01-12','Tecnam Sierra','Tecnam','24-7155',600,2002,'Recreational','YCDR','YCDR',1,'0',0);
INSERT INTO Flight_Log VALUES (10,'2023-01-18','Tecnam Sierra','Tecnam','24-7155',600,2002,'Recreational','YCDR','YCDR',4,'0',0);
INSERT INTO Flight_Log VALUES (11,'2023-01-27','Tecnam Sierra','Tecnam','24-7155',600,2002,'Recreational','YCDR','YCDR',3,'0',0);
INSERT INTO Flight_Log VALUES (12,'2023-02-03','Tecnam Sierra','Tecnam','24-7155',600,2002,'Recreational','YCDR','YCDR',3,'0',0);
INSERT INTO Flight_Log VALUES (13,'2023-02-14','Tecnam P-92 Eaglet','Tecnam','24-5955',600,1992,'Recreational','YCDR','YCDR',1,'0',1);
INSERT INTO Flight_Log VALUES (14,'2023-02-14','Tecnam P-92 Eaglet','Tecnam','24-5955',600,1992,'Recreational','YCDR','YCDR',1,'0',1);
INSERT INTO Flight_Log VALUES (15,'2023-03-14','Tecnam P-92 Eaglet','Tecnam','24-5955',600,1992,'Recreational','YCDR','YCDR',1,'0',1);
INSERT INTO Flight_Log VALUES (16,'2023-03-14','Tecnam P-92 Eaglet','Tecnam','24-5955',600,1992,'Recreational','YCDR','YCDR',1,'0',1);
INSERT INTO Flight_Log VALUES (17,'2023-03-28','Cessna 172R','Cessna','VH-CFG',1111,1997,'Recreational','YCDR','YCDR',3,'1',0);
INSERT INTO Flight_Log VALUES (18,'2023-04-06','Cessna 172 G1000','Cessna','VH-IVW',1156,2013,'Recreational','YRED','YRED',3,'1',0);
INSERT INTO Flight_Log VALUES (19,'2023-04-19','Cessna 172 G1000','Cessna','VH-IVW',1156,2013,'Recreational','YRED','YCDR',2,'1',0);
INSERT INTO Flight_Log VALUES (20,'2023-04-23','Cirrus SR22','Cirrus','VH-EDH',1633,2014,'Recreational','YBAF','YBAF',2,'1',0);
INSERT INTO Flight_Log VALUES (21,'2023-05-02','Cirrus SR22','Cirrus','VH-EDH',1633,2014,'Recreational','YBAF','YBAF',2,'1',0);
What am I doing wrong? (I am using the newest version of MySQL (8.0.31))
When you are mixing aggregate functions (SUM in your case) and plain columns in select you will need a GROUP BY statement telling over which set the aggregate function is calculated from.
You are also using FlightTim and sum(FlightTime) at same level. Over which set do you want the sum(FlightTime) to be calculated?
Modify the question to include sample data with expected results.
So I recreated your table:
INSERT INTO public.flights(
flight_number, flight_time, tail_number)
VALUES
(1, 20, '24-5955'),
(2, 25, '24-5874'),
(3, 32, '24-1111'),
(4, 7, 'VH-1234'),
(5, 5, '24-5955'),
(6, 8, '24-9874'),
(7, 25, '24-5555');
Which gives me this:
Query you should have:
select f2.flight_number, f2.flight_time, f1.tail_number,
CASE
WHEN f1.flight_time >= 20 AND f1.flight_time < 25 AND f1.tail_number LIKE '24-%' THEN 'RAAus Recreational Pilots Certificate (RPC)'
WHEN f1.flight_time >= 25 AND f1.flight_time < 32 AND f1.tail_number LIKE '24-%' THEN 'RAAus RPC Passenger Endorsment'
WHEN f1.flight_time >= 32 AND f1.tail_number LIKE '24-%' THEN 'RAAus RPC Cross Country Endorsment'
WHEN f1.flight_time >= 7 AND f1.tail_number LIKE 'VH-%' THEN 'RPC Conversion to CASA Recreational Pilot License (RPL)'
ELSE 'Eligibility Checker Error'
END as "License Eligibility"
FROM (SELECT sum(flight_time) as flight_time, tail_number FROM flights group by tail_number) f1
INNER JOIN flights f2
on f1.tail_number = f2.tail_number
group by f2.flight_number, f1.tail_number, f1.flight_time
order by flight_number
this gives me:
Just add the other columns you have with its alias' and you should be good. If this isn't what you want, please provide the exercise statement.
For your DATASET this query will be:
select flightnumber as "Flight Number", "Date", aircraft, Aircraft_Manufacturer AS "Aircraft Manufacturer", f1.Tail_Number AS "Tail Number", Departure, Arrival, FlightTime AS "Flight Time", Instructor, Passengers,
CASE
WHEN f1.flight_time >= 20 AND f1.flight_time < 25 AND f1.tail_number LIKE '24-%' THEN 'RAAus Recreational Pilots Certificate (RPC)'
WHEN f1.flight_time >= 25 AND f1.flight_time < 32 AND f1.tail_number LIKE '24-%' THEN 'RAAus RPC Passenger Endorsment'
WHEN f1.flight_time >= 32 AND f1.tail_number LIKE '24-%' THEN 'RAAus RPC Cross Country Endorsment'
WHEN f1.flight_time >= 7 AND f1.tail_number LIKE 'VH-%' THEN 'RPC Conversion to CASA Recreational Pilot License (RPL)'
ELSE 'Eligibility Checker Error'
END as "License Eligibility"
FROM (SELECT sum(flighttime) as flight_time, tail_number as tail_number FROM Flight_Log group by Tail_Number) f1
INNER JOIN Flight_Log f2
on f1.tail_number = f2.Tail_Number
group by flightnumber, f1.tail_number, f1.flight_time
order by flightnumber
IMPORTANT: It is normal that the License Eligibility is an Error everywhere...
When running this query:
select sum(flighttime), tail_number from Flight_Log
group by tail_number
we can see that all flightnumbers with tail number starting with 24 are under 20 hours --> So error
And also the tailnumbers with VH are all under 7 --> Error.
If you add more data and more hours to all tail_numbers you will see my query works

Query to display row after 1 pm

How to fetch all rows from table where time is greater than 13:00 i.e. 1PM
SELECT * FROM `mytable` WHERE `time` >="13:00";
if you have a datetime field you could do this (I'm assuming here as you haven't specified):
create table tester(`id` int(6), `name` varchar(50), `datetest` datetime);
insert into tester(`id`,`name`,`datetest`)
values(1, 'n1', '2018-12-20 09:00:00'),
(2, 'n2', '2018-12-20 10:00:00'),
(3, 'n3', '2018-12-20 13:10:00'),
(4, 'n4', '2018-12-20 14:00:00');
select * from tester
where TIME(datetest) > '13:00'

Bookings system

This is the database schema:
CREATE TABLE `bookings` (
`id` int(2) NOT NULL,
`start` time NOT NULL,
`end` time NOT NULL
)
INSERT INTO `bookings` VALUES(1, '13:00:00', '14:30:00');
INSERT INTO `bookings` VALUES(2, '15:00:00', '16:00:00');
I tried to run the following query, to find the free times:
SELECT free_from, free_until
FROM (SELECT a.end AS free_from,
(SELECT MIN(c.start)
FROM bookings c
WHERE c.start>a.end
) as free_until
FROM bookings a
WHERE NOT EXISTS (SELECT 1
FROM bookings b
WHERE b.start BETWEEN a.end AND a.end + INTERVAL your_duration HOURS
) AND
a.end BETWEEN '10:00:00' AND '18:00:00'
) t
The output generated is:
free_from free_until
14:30:00 15:00:00
16:00:00 NULL
Why is there a NULL in the end? Please help me solve this problem. Expected output should be:
free_from free_until
10:00:00 13:00:00
14:30:00 15:00:00
16:00:00 18:00:00
try this:
first create table and insert records
CREATE TABLE bookings (
id int NOT NULL,
start time NOT NULL,
endtime time NOT NULL
)
INSERT INTO bookings VALUES(1, '13:00:00', '14:30:00');
INSERT INTO bookings VALUES(2, '15:00:00', '16:00:00');
then run this select query
SELECT free_from, free_until
FROM (SELECT a.endtime AS free_from,
(SELECT MIN(c.start)
FROM bookings c
WHERE c.start>a.endtime
) as free_until
FROM bookings a
WHERE a.endtime BETWEEN '10:00:00' AND '18:00:00'
) t where free_until IS NOT NULL;
Note: I changed your column end to endtime
The first row of your output corresponds to the following data set:
a:
1, '13:00:00', '14:30:00'
c:
1, '13:00:00', '14:30:00'
2, '15:00:00', '16:00:00'
for "free_until", c.start must be higher than a.end, which is satisfied for this data set.(for 2nd row of C)
The second row of your output corresponds to the following data set:
a:
2, '15:00:00', '16:00:00'
c:
1, '13:00:00', '14:30:00'
2, '15:00:00', '16:00:00'
for "free_until", c.start>a.end but as you can see, a.end is 16:00 here, and no c.start is higher than this.
that's why null
Modify a.end of the second row to 14:00 and you will not get null value. :D
modify the data in the table:
Delete everything from bookings, then
INSERT INTO `bookings` VALUES(1, '13:00:00', '14:30:00');
INSERT INTO `bookings` VALUES(2, '15:00:00', '14:00:00');

Find overlapping prescriptions

I have a bunch of patient prescriptions, each having a certain start date and an end date. I would like to find the instances where a patient has been taking more than one drug in the same drug category for more than 2 days. duration should overlap.
Table structure looks like this:
PatientID StartDate EndDate Drug DrugCategory
1 1/1/2013 1/5/2013 A Cat1
1 1/1/2013 1/4/2013 B Cat1
1 1/10/2013 1/12/2013 C Cat1
2 ....... ........ ............. .........
As seen above, Patient-1 was prescribed 3 drugs in the same category and the first two drug overlapped in duration more than 2 days. So, for this example, I would like the query return the first two records for Patient-1 along with drug name, patientid.
Hope someone can help. This is using SQL Server 2008 R2 btw.
Do you want them as separate rows or as one row? If you want them as separate rows, this should work; otherwise you can pivot the result.
create table want as
select H.* from have H, have V
where H.drug ne V.drug
and H.PatientID=V.PatientID
and H.startDate <= V.startDate
and V.startDate <= H.endDate-2
union select V.* from have H, have V
where H.drug ne V.drug
and H.PatientID=V.PatientID
and H.startDate <= V.startDate
and V.startDate <= H.endDate-2
;
I union the H and V records, I'm sure there's a more efficient way to do that but couldn't easily come up with one. (Just H works for the example given, but for a more proper example where the start dates are not always equal you need the V row as well.)
Please test this thoroughly before using. I have tested it and so far it looks good but not done an exhaustive testing. Would be great if you can test it out further sufficient to your requirements and can point any anomalies in the result if present or take it forward and modify if required.
--Test data:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[Prescriptions](
[PatientID] [int] NULL,
[StartDate] [datetime] NULL,
[EndDate] [datetime] NULL,
[Drug] [varchar](50) NULL,
[DrugCategory] [varchar](50) NULL
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
INSERT [dbo].[Prescriptions] ([PatientID], [StartDate], [EndDate], [Drug], [DrugCategory]) VALUES (1, CAST(0x0000A13A00000000 AS DateTime), CAST(0x0000A13E00000000 AS DateTime), N'D', N'Cat1')
INSERT [dbo].[Prescriptions] ([PatientID], [StartDate], [EndDate], [Drug], [DrugCategory]) VALUES (1, CAST(0x0000A13A00000000 AS DateTime), CAST(0x0000A13B00000000 AS DateTime), N'E', N'Cat1')
INSERT [dbo].[Prescriptions] ([PatientID], [StartDate], [EndDate], [Drug], [DrugCategory]) VALUES (1, CAST(0x0000A13800000000 AS DateTime), CAST(0x0000A13B00000000 AS DateTime), N'F', N'Cat1')
INSERT [dbo].[Prescriptions] ([PatientID], [StartDate], [EndDate], [Drug], [DrugCategory]) VALUES (1, CAST(0x0000A13800000000 AS DateTime), CAST(0x0000A13900000000 AS DateTime), N'G', N'Cat1')
INSERT [dbo].[Prescriptions] ([PatientID], [StartDate], [EndDate], [Drug], [DrugCategory]) VALUES (1, CAST(0x0000A12300000000 AS DateTime), CAST(0x0000A13900000000 AS DateTime), N'Z', N'Cat1')
INSERT [dbo].[Prescriptions] ([PatientID], [StartDate], [EndDate], [Drug], [DrugCategory]) VALUES (1, CAST(0x0000A12300000000 AS DateTime), CAST(0x0000A13A00000000 AS DateTime), N'Y', N'Cat1')
INSERT [dbo].[Prescriptions] ([PatientID], [StartDate], [EndDate], [Drug], [DrugCategory]) VALUES (1, CAST(0x0000A13900000000 AS DateTime), CAST(0x0000A13D00000000 AS DateTime), N'A', N'Cat1')
INSERT [dbo].[Prescriptions] ([PatientID], [StartDate], [EndDate], [Drug], [DrugCategory]) VALUES (1, CAST(0x0000A13900000000 AS DateTime), CAST(0x0000A13C00000000 AS DateTime), N'B', N'Cat1')
INSERT [dbo].[Prescriptions] ([PatientID], [StartDate], [EndDate], [Drug], [DrugCategory]) VALUES (1, CAST(0x0000A14200000000 AS DateTime), CAST(0x0000A14400000000 AS DateTime), N'C', N'Cat1')
Query Used:
SELECT DISTINCT PatientID,StartDate,EndDate,Drug,DrugCategory FROM (
SELECT
DATEDIFF(dd,a.startdate,b.startdate) c1
,DATEDIFF(dd,a.enddate,b.enddate)c2
,DATEDIFF(dd,a.startdate,b.enddate) c3
,DATEDIFF(dd,a.enddate,b.startdate) c4
,DATEDIFF(dd,a.startdate,b.enddate)+DATEDIFF(dd,a.enddate,b.startdate) c34
,a.PatientID
,a.StartDate
,a.EndDate
,a.Drug
,a.DrugCategory
,b.PatientID AS PatientID1
,b.StartDate AS StartDate1
,b.EndDate AS EndDate1
,b.Drug AS Drug1
,b.DrugCategory DrugCategory1
FROM Prescriptions a
,Prescriptions b
WHERE a.patientid=b.patientid
AND a.DrugCategory= b.DrugCategory
and a.drug<>b.drug
)a
WHERE c1*c2*c3*c4 <0
AND c3>2
and c4<=-2
ORDER BY 1,2,3,4
Results:
PatientID StartDate EndDate Drug DrugCategory
----------- ----------------------- ----------------------- -------------------------------------------------- --------------------------------------------------
1 2012-12-10 00:00:00.000 2013-01-02 00:00:00.000 Y Cat1
1 2012-12-31 00:00:00.000 2013-01-03 00:00:00.000 F Cat1
1 2013-01-01 00:00:00.000 2013-01-04 00:00:00.000 B Cat1
1 2013-01-01 00:00:00.000 2013-01-05 00:00:00.000 A Cat1
1 2013-01-02 00:00:00.000 2013-01-06 00:00:00.000 D Cat1
(5 row(s) affected)
what you should be able to do is join the prescription table to itself on the patientID and drugCategory fields where the drugName differs and the startDate OR endDate of the 2nd instance spans the startDate/endDate of the first. Then, determine the overlap range by subtracting the number of days between the max(startDates) and min(endDates). If the overlap is greater than 2 days, return the row:
select *, datediff(d, start_max, end_min) as overlap
from (
SELECT
P.PatientID, P.StartDate, P.EndDate, P.Drug, P.DrugCategory,
P1.StartDate AS p1_start, P1.EndDate AS p1_end, P1.Drug AS p1_drug,
CASE WHEN p.startdate >= P1.startdate THEN p.startdate ELSE P1.startdate END AS start_max,
CASE WHEN p.EndDate <= P1.EndDate THEN p.EndDate ELSE P1.EndDate END AS end_min
FROM
dbo.Prescriptions p INNER JOIN
dbo.Prescriptions AS P1 ON
P.PatientID = P1.PatientID AND
P.DrugCategory = P1.DrugCategory AND
P.Drug <> P1.Drug
WHERE
(P1.StartDate >= P.StartDate AND P1.StartDate <= P.EndDate) OR
(P1.EndDate >= P.StartDate AND P1.EndDate <= P.EndDate)
) t
where
datediff(d, start_max, end_min) > 2