I have a large table ~25 million rows with the structure
CREATE TABLE [dbo].[rx](
[pat_id] [int] NOT NULL,
[fill_Date] [date] NOT NULL,
[script_End_Date] AS (dateadd(day,[dayssup],[filldate])) persisted,
[drug_Name] [varchar](50) NULL,
[days_Sup] [int] NOT NULL,
[quantity] [float] NOT NULL,
[drug_Class] [char](3) NOT NULL,
CHECK(fill_Date <=script_End_Date
PRIMARY KEY NONCLUSTERED
(
[clmid]
)
create clustered index ix_rx_temporal on rx(fill_date asc, script_end_date asc, pat_id asc)
The primary key on this table is never queried on. This table by far is used most often with queries that involve date ranges. I have a calendar table with the structure
CREATE TABLE [dbo].[Calendar](
[cal_date] [date] PRIMARY KEY,
[Year] AS YEAR(cal_date) PERSISTED,
[Month] AS MONTH(cal_date) PERSISTED,
[Day] AS DAY(cal_date) PERSISTED,
[julian_seq] AS 1+DATEDIFF(DD, CONVERT(DATE, CONVERT(varchar,YEAR(cal_date))+'0101'),cal_date));
The query that I'm trying to speed up is:
;WITH x
AS (
--join finds the amount of distinct drugs that a person was prescribed on a given day
SELECT rx.pat_id,
c.cal_date,
Count(DISTINCT rx.drug_name) AS distinctDrugs
FROM rx,
calendar AS c
WHERE c.cal_date BETWEEN rx.fill_date AND rx.script_end_date
GROUP BY rx.pat_id,
c.cal_date),
y
AS (
--makes a sequence so that contiguous dates can be grouped together as a date range
SELECT x.pat_id,
x.distinctdrugs,
c2.julian_seq- Row_number()
OVER(
partition BY x.pat_id, distinctdrugs
ORDER BY x.cal_date) AS rn,
x.cal_date
FROM x,
calendar AS c2
WHERE c2.cal_date = x.cal_date)
--finds the max and minimum dates which a person was taking X amoung of drugs
SELECT y.pat_id,
Min(y.cal_date) AS min_overlap,
Max(y.cal_date) AS max_overlap,
Min(distinctdrugs) AS distinctDrugs
FROM y
GROUP BY y.pat_id,
rn
I tried a couple of the following indexes
CREATE NONCLUSTERED INDEX [ix_rx2] ON [dbo].[rx]
(
[drug_name] ASC,
[drug_class] ASC,
[fill_date] ASC,
[script_end_date] ASC
)
and
CREATE NONCLUSTERED INDEX [ix_rx3] ON [dbo].[rx]
(
[fill_date] ASC,
[script_end_date] ASC
)
INCLUDE ( [pat_id],
[drug_class],
[drug_name])
Whenever I check out the execution plan, none of the indexes on the rx table are being used. There are other aspects of the execution plan, but the bulk of it looks like

I even tried removing the current clustered index and just using (fill_date,admi_date) and yet I still can't find a way to keep from running into that hash match operator in the execution plan that is taking up the vast majority of the resources for this query. The primary key on the rx table is never queried on, and I'll primarily be doing queries involving date ranges with this table. The indexes on the tables have nominal fragmentation and the densities of the indexes are all very low. What can I do do speed up this query, or am I going to be limited by hardware?
script_end_datecolumn so that it's persisted, if that makes any difference. – wootscootinboogie Feb 11 at 19:16DISTINCT- is it really possible for the same patient to be prescribed the same drug more than once for the same day? – Paul White Feb 13 at 3:06