我对ms sql很新,所以请原谅
我有一个表格,其中包含来自客户端和管理员的所有评论。我必须随着查询的放置时间和首次确认的时间选择唯一的会话。
查询是:
SELECT CONVERT(DATE, [t0].[CommDate]) AS [CommDate2], [t0].[TicketId], [t0].[TransactionID], (
SELECT MIN([t1].[CommDate])
FROM [dbo].[CommentsHistory] AS [t1]
WHERE ([t1].[TicketId] = [t0].[TicketId]) AND ([t1].[CommentFrom] LIKE '%Client%')
) AS [AskedMinDate], (
SELECT MIN([t2].[CommDate])
FROM [dbo].[CommentsHistory] AS [t2]
WHERE ([t2].[TicketId] = [t0].[TicketId]) AND (NOT ([t2].[CommentFrom] LIKE '%Client%'))
) AS [ResponseMinDate] FROM [dbo].[CommentsHistory] AS [t0]
WHERE (CONVERT(DATE, [t0].[CommDate]) >= DATEADD(mm,-1,GETDATE())) AND ([t0].[TicketId] IS NOT NULL)
ORDER BY [t0].[TicketId] DESC, [t0].[CommDate]
我已经应用了索引,但由于列内容不是唯一的,所以没有多大帮助。
还有其他方法可以编写这些类型的查询,还是应该考虑重构表本身?
上面的查询给出了结果,但速度太慢,我想知道我的查询不是优化的,或者我选择的表创建是错误的?
表格结构:
CREATE TABLE [dbo].[CommentsHistory](
[ID] [int] IDENTITY(1,1) NOT NULL,
[CommDate] [datetime] NULL CONSTRAINT [DF_CommentsHistory_CommDate] DEFAULT (getdate()),
[CommentFrom] [varchar](255) NULL,
[Comments] [varchar](max) NULL,
[TransactionID] [float] NULL,
[splitnumber] [varchar](50) NULL,
[MfrId] [int] NULL,
[ShowClient] [bit] NULL,
[ShowWareHouse] [bit] NULL,
[IsResponse] [bit] NULL,
[CustEmail] [varchar](150) NULL,
[TicketId] [numeric](18, 0) NULL
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
答案 0 :(得分:1)
你没有提供任何数据来测试,但我的直觉是将子查询作为WITH
子句运行会运行得更快,因为它们会运行一次并加入,而不是每次运行主结果集中的行。
WITH CLIENTCOMMENTDATE
AS (SELECT [t1].[TicketId], MIN([t1].[CommDate]) AS [CommDate]
FROM [dbo].[CommentsHistory] AS [t1]
WHERE ([t1].[CommentFrom] LIKE '%Client%')
GROUP BY [t1].[TicketId]
)
, RESPONSEDATE
AS (SELECT [t2].[TicketId], MIN([t2].[CommDate]) AS [CommDate]
FROM [dbo].[CommentsHistory] AS [t2]
WHERE (NOT ([t2].[CommentFrom] LIKE '%Client%'))
GROUP BY [t2].[TicketId]
)
SELECT CONVERT(DATE, [t0].[CommDate]) AS [CommDate2],
[t0].[TicketId], [t0].[TransactionID],
[t1].[CommDate] AS [AskedMinDate],
[t2].[CommDate] AS [ResponseMinDate]
FROM [dbo].[CommentsHistory] AS [t0]
LEFT JOIN CLIENTCOMMENTDATE [t1] ON [t1].[TicketId] = [t0].[TicketId]
LEFT JOIN RESPONSEDATE [t2] ON [t2].[TicketId] = [t0].[TicketId]
WHERE (CONVERT(DATE, [t0].[CommDate]) >= DATEADD(mm,-1,GETDATE()))
AND ([t0].[TicketId] IS NOT NULL)
ORDER BY [t0].[TicketId] DESC, [t0].[CommDate]
;
另一件能加速它的事情是,如果不是LIKE
运算符,你可以使用等于运算符,例如 [CommentFrom] = 'Client'
。这取决于评论来自客户端时CommentFrom
列的内容是否始终正好'Client'
。如果是,则可以使用相等运算符。如果没有,也许该列始终以'Client'
开始,或者它始终位于值中的相同位置,因此您可以使用LEFT
或SUBSTRING
,例如 LEFT([CommentFrom], 6) = 'Client'
。
答案 1 :(得分:0)
尝试使用OUTER APPLY,如下所示。
您可能需要在此查询中进行一些修改
SELECT CONVERT(DATE, [t0].[CommDate]) AS [CommDate2],
[t0].[TicketId], [t0].[TransactionID],
A.AskedMinDate,
B.ResponseMinDate
FROM [dbo].[CommentsHistory] AS [t0]
OUTER APPLY (
SELECT MIN([t1].[CommDate]) AS AskedMinDate
FROM [dbo].[CommentsHistory] AS [t1]
WHERE ([t1].[TicketId] = [t0].[TicketId]) AND ([t1].[CommentFrom] LIKE '%Client%')
) AS A
OUTER APPLY (
SELECT MIN([t2].[CommDate]) AS ResponseMinDate
FROM [dbo].[CommentsHistory] AS [t2]
WHERE ([t2].[TicketId] = [t0].[TicketId]) AND (NOT ([t2].[CommentFrom] LIKE '%Client%'))
) AS B
WHERE (CONVERT(DATE, [t0].[CommDate]) >= DATEADD(mm,-1,GETDATE())) AND ([t0].[TicketId] IS NOT NULL)
ORDER BY [t0].[TicketId] DESC, [t0].[CommDate]