Is there any way to optimize this stored procedure? Maybe something instead of so many joins? It takes some time to execute. Maybe there are other options that I could look into?
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [stimulator].[GetLastMessages2]
@serviceId bigint,
@stimulatorId int,
@from datetime,
@to datetime,
@atLeast int = null,
@lessThan int = null,
@lastHourLessThan int = null,
@hourFactor int = 24,
@lastXHourLessThan int = null,
@totalLessThan int = null
AS
BEGIN
SET NOCOUNT ON;
DECLARE @H1Ago datetime
DECLARE @HXAgo datetime
DECLARE @Now datetime
DECLARE @Today datetime
SET @H1Ago = DATEADD(hh, -1, getdate())
SET @HXAgo = DATEADD(hh, -@hourFactor, getdate())
SET @Now = getdate()
SET @Today = DATEADD(dd, 0, DATEDIFF(dd, 0, @Now))
SELECT tel_telewidz,
acn_id,
guid,
[First],
[Last],
[inCount],
isNULL(lastHourCount, 0) lastHourCount,
isNULL(lastXCount, 0) lastXCount,
isNULL(allCount, 0) allCount,
lastStimulation,
body,
STUFF((SELECT '|' + body
FROM SP_BILLING_DW.hurt.MESSAGE_In inmsg
WHERE inmsg.tel_telewidz = d.tel_telewidz
AND service_id = @serviceId
AND creation_time > @from
AND creation_time <= @to
FOR XML PATH('')), 1, 1, '') [allbody]
FROM (
SELECT tel_telewidz, acn_id, guid, creation_time, service_id
,ROW_NUMBER() OVER(PARTITION BY tel_telewidz ORDER BY creation_time) [No]
,COUNT(*) OVER(PARTITION BY tel_telewidz) [inCount]
,MIN(creation_time) OVER(PARTITION BY tel_telewidz) [First]
,MAX(creation_time) OVER(PARTITION BY tel_telewidz) [Last]
,body
FROM SP_BILLING_DW.hurt.MESSAGE_In
WHERE
creation_time > @from
AND
creation_time <= @to
AND
service_id = @serviceId
) d
LEFT JOIN
(
SELECT msisdn, count(*) lastHourCount
FROM stimulator.SentMessages
WHERE serviceId = @serviceId
AND stimulatorId = @stimulatorId
AND sendDate > @H1Ago
GROUP BY msisdn
) lh ON d.tel_telewidz = lh.msisdn
LEFT JOIN
(
SELECT msisdn, count(*) lastXCount
FROM stimulator.SentMessages
WHERE serviceId = @serviceId
AND stimulatorId = @stimulatorId
AND sendDate > @HXAgo
GROUP BY msisdn
) ld ON d.tel_telewidz = ld.msisdn
LEFT JOIN
(
SELECT msisdn, count(*) allCount
FROM stimulator.SentMessages
WHERE serviceId = @serviceId
AND stimulatorId = @stimulatorId
AND sendDate > @from
GROUP BY msisdn
) nDays ON d.tel_telewidz = nDays.msisdn
LEFT JOIN
(
SELECT msisdn, max(sendDate) lastStimulation
FROM stimulator.SentMessages
WHERE serviceId = @serviceId
AND stimulatorId = @stimulatorId
AND sendDate > @from
GROUP BY msisdn
) ls ON d.tel_telewidz = ls.msisdn
WHERE
d.[No] = d.[inCount]
AND
((@atLeast IS NULL) OR (d.[inCount] >= @atLeast))
AND
((@lessThan IS NULL) OR (d.[inCount] < @lessThan))
AND
((@lastHourLessThan IS NULL) OR (lastHourCount IS NULL) OR (lastHourCount < @lastHourLessThan))
AND
((@lastXHourLessThan IS NULL) OR (lastXCount IS NULL) OR (lastXCount < @lastXHourLessThan))
AND
((@totalLessThan IS NULL) OR (allCount IS NULL) OR (allCount < @totalLessThan))
END
Here are the tables involved:
stimulator.SentMessages
CREATE TABLE [stimulator].[SentMessages](
[Id] [int] IDENTITY(1,1) NOT NULL,
[serviceId] [bigint] NOT NULL,
[stimulatorId] [int] NOT NULL,
[guid] [uniqueidentifier] NOT NULL,
[sendDate] [datetime] NOT NULL,
[msisdn] [varchar](16) NOT NULL,
[body] [varchar](1024) NOT NULL,
CONSTRAINT [PK_st_sentmess] PRIMARY KEY CLUSTERED
(
[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
ALTER TABLE [stimulator].[SentMessages] ADD CONSTRAINT [DF_SentMessages_sendDate] DEFAULT (getdate()) FOR [sendDate]
GO
hurt.MESSAGE_In
CREATE TABLE [hurt].[MESSAGE_In](
[ID] [bigint] NOT NULL,
[guid] [uniqueidentifier] NOT NULL,
[tel_telewidz] [varchar](50) NULL,
[tel_operator] [varchar](50) NULL,
[msg_type] [char](1) NULL,
[direction] [char](1) NULL,
[udh] [varchar](900) NULL,
[body] [varchar](900) NULL,
[mms_subject] [varchar](900) NULL,
[acn_id] [smallint] NULL,
[require_status_report] [tinyint] NULL,
[creation_time] [datetime] NOT NULL,
[is_spam] [tinyint] NULL,
[is_binary_sms] [tinyint] NULL,
[partner_guid] [varchar](50) NULL,
[reply_to_guid] [uniqueidentifier] NULL,
[expected_no_of_parts] [tinyint] NULL,
[transmitted_parts_no] [tinyint] NULL,
[data_insertu] [datetime] NOT NULL,
[data_update] [datetime] NOT NULL,
[tel_operator_nadpis] [varchar](50) NULL,
[machineName] [varchar](50) NULL,
[service_id] [int] NULL,
[client_id] [int] NULL,
[partner_id] [int] NULL,
[operatorMnemonic] [char](1) NULL,
[status_wysylki] [tinyint] NULL,
[data_wysylki] [datetime] NULL,
[opis_wysylki] [varchar](500) NULL,
[status_dostarczenia] [tinyint] NULL,
[data_dostarczenia] [datetime] NULL,
[opis_dostarczenia] [varchar](500) NULL,
[status_obslugi] [tinyint] NULL,
[has_ack] [tinyint] NULL,
[in_sent_time] [datetime] NULL,
[ev_ServiceUpdate] [datetime] NULL,
CONSTRAINT [PK_MESSAGE_In_new] PRIMARY KEY CLUSTERED
(
[creation_time] ASC,
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON)
)
GO
SET ANSI_PADDING OFF
GO