Sql 如何优化包含来自同一表的子查询的查询?
我对sql女士很陌生,请原谅 我有一个表,其中包含来自客户端以及管理员的所有评论。我必须根据放置查询的时间和首次确认查询的时间选择唯一会话 查询是:Sql 如何优化包含来自同一表的子查询的查询?,sql,sql-server,sql-server-2008,Sql,Sql Server,Sql Server 2008,我对sql女士很陌生,请原谅 我有一个表,其中包含来自客户端以及管理员的所有评论。我必须根据放置查询的时间和首次确认查询的时间选择唯一会话 查询是: SELECT CONVERT(DATE, [t0].[CommDate]) AS [CommDate2], [t0].[TicketId], [t0].[TransactionID], ( SELECT MIN([t1].[CommDate]) FROM [dbo].[CommentsHistory] AS [t1] WHERE ([t1].[
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]
尝试使用外部应用,如下所示 您可能需要在此查询中进行一些修改
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]
您没有提供任何要测试的数据,但我的直觉是,使用子句作为
运行子查询会运行得更快,因为它们只运行一次并加入,而不是针对主结果集中的每一行运行
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([CommentFrom],6)='Client'
请告诉我们您想要做什么。我无法查看您的代码并想象您想要什么。查询需要很长时间才能完成。我看到很多自连接。你为什么这么做?顺便说一句,你介意显示你期望的输出的屏幕截图吗?我已经上传了图片。像“%Client%”这样的评论正是影响你性能的原因。您需要正确地修改逻辑,或者使用公共表表达式和窗口函数来限制您选择的数据,而不是子查询,或者使用一些预先计算的值。