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].[

我对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]

尝试使用外部应用,如下所示

您可能需要在此查询中进行一些修改

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%”这样的
评论
正是影响你性能的原因。您需要正确地修改逻辑,或者使用公共表表达式和窗口函数来限制您选择的数据,而不是子查询,或者使用一些预先计算的值。