SQL - 要子查询还是不查询子查询?

时间:2014-04-23 13:26:59

标签: sql tsql

我在使用大量记录填充数据库时无法进行速度测试。任何人都可以告诉我在处理数百万条记录时哪个查询应该更快?我喜欢Tomas'查询最多,但是在处理更大的桌子时,DISTINCT不会放慢速度吗?

我很惊讶地看到我的子查询并没有像我想象的那样减慢速度。

::我的。在00.0640419中生成22行> 00.1030255秒。

SELECT
    [planning].[id] as planningId,
    [planning].[type] as planningType,
    [planning].[from] as planningFrom,
    [planning].[till] as planningTill,
    [worker].[intId] as workerId,
    [worker].[name] as workerName,
    [site].[intId] as siteId,
    [site].[name] as siteName
FROM
    [worker]
    LEFT JOIN [planning] ON [planning].[workerId] = [worker].[intId] AND [planning].[companyId] = [worker].[companyId]
    LEFT JOIN [site] ON [planning].[siteId] = [site].[intId] AND [planning].[companyId] = [site].[companyId]
WHERE 
    [worker].[companyId] = 2
    AND ( [planning].[id] IS NULL  OR  ( [planning].[from] <= '2014-04-30' AND [planning].[till] >= '2014-04-01') )
    AND ([worker].[intId] IN (
        SELECT 
          [worker].[intId] 
        FROM 
          [planning]
          INNER JOIN [worker] ON [planning].[workerId] = [worker].[intId] AND [planning].[companyId] = [worker].[companyId]
        WHERE
          [worker].[companyId] = 2
          AND ([planning].[type] = 'absent' OR ([planning].[siteId] IN ('7710122')))
      ) OR [worker].[intId] IN ('7701260')
  )

:: Sirko。在00.0684108中生成22行&gt; 00.0955292秒。

SELECT
    [planning].[id] as planningId,
    [planning].[type] as planningType,
    [planning].[from] as planningFrom,
    [planning].[till] as planningTill,
    [worker].[intId] as workerId,
    [worker].[name] as workerName,
    [site].[intId] as siteId,
    [site].[name] as siteName
FROM
    [worker]
    LEFT JOIN [planning] ON [planning].[workerId] = [worker].[intId] AND [planning].[companyId] = [worker].[companyId]
    LEFT JOIN [site] ON [planning].[siteId] = [site].[intId] AND [planning].[companyId] = [site].[companyId]
    LEFT JOIN ( SELECT DISTINCT
                    [worker].[intId] 
                FROM 
                    [planning]
                    LEFT JOIN [worker] ON [planning].[workerId] = [worker].[intId] AND [planning].[companyId] = [worker].[companyId]
                WHERE
                    [worker].[companyId] = 2
                    AND ([planning].[type] = 'absent' OR ([planning].[type] = 'site' AND [planning].[siteId] IN ('7710122')))
               ) AS filter ON filter.[intId] = [worker].[intId]
WHERE 
    [worker].[companyId] = 2
    AND ( ( [planning].[from] <= '2014-04-30' AND [planning].[till] >= '2014-04-01') OR [worker].[intId] IN ('7701260') )

:: Tomas Pastircak。在00.0674178中生成22行> 00.0850567秒。

SELECT DISTINCT
    [planning].[id] as planningId,
    [planning].[type] as planningType,
    [planning].[from] as planningFrom,
    [planning].[till] as planningTill,
    [worker].[intId] as workerId,
    [worker].[name] as workerName,
    [site].[intId] as siteId,
    [site].[name] as siteName
FROM
    [worker]
    LEFT JOIN [planning] ON [planning].[workerId] = [worker].[intId] AND [planning].[companyId] = [worker].[companyId]
    LEFT JOIN [site] ON [planning].[siteId] = [site].[intId] AND [planning].[companyId] = [site].[companyId]
    LEFT JOIN [planning] p2 ON p2.[workerId] = [worker].[intId] AND p2.[companyId] = [worker].[companyId]
WHERE 
    [worker].[companyId] = 2
        AND ( [planning].[id] IS NULL  OR  ( [planning].[from] <= '2014-04-30' AND [planning].[till] >= '2014-04-01') )
    AND (p2.[type] = 'absent' OR p2.[siteId] IN ('7710122') OR [worker].[intId] IN ('7701260'))

3 个答案:

答案 0 :(得分:1)

有没有理由为什么你不能将它添加到WHERE条件中,没有所有子查询的东西?它似乎返回相同的数据......

SELECT
...
FROM
...
LEFT JOIN [planning] p2 ON p2.[workerId] = [worker].[intId] AND p2.[companyId] = [worker].[companyId]

WHERE 
    [worker].[companyId] = 2
    AND ( [planning].[id] IS NULL  OR  ( [planning].[from] <= '2014-04-30' AND [planning].[till] >= '2014-04-01') )
    AND (p2.[type] = 'absent' OR (p2.[type] = 'site' AND p2.[siteId] IN ('7710122'))

答案 1 :(得分:1)

我并不完全熟悉T-SQL语法,但以下内容应该有效:

SELECT
    [planning].[id] as planningId,
    [planning].[type] as planningType,
    [planning].[from] as planningFrom,
    [planning].[till] as planningTill,
    [planning].[busyMon] as busyMon,
    [planning].[busyTue] as busyTue,
    [planning].[busyWed] as busyWed,
    [planning].[busyThu] as busyThu,
    [planning].[busyFri] as busyFri,
    [planning].[busySat] as busySat,
    [planning].[busySun] as busySun,
    [planning].[busyHolidays] as busyHolidays,
    [worker].[intId] as workerId,
    [worker].[name] as workerName,
    [worker].[partner] as workerPartner,
    [site].[intId] as siteId,
    [site].[name] as siteName
FROM
    [worker]
    LEFT JOIN [planning] ON [planning].[workerId] = [worker].[intId] AND [planning].[companyId] = [worker].[companyId]
    LEFT JOIN [site] ON [planning].[siteId] = [site].[intId] AND [planning].[companyId] = [site].[companyId]
    LEFT JOIN ( SELECT DISTINCT
                    [worker].[intId] 
                FROM 
                    [planning]
                    LEFT JOIN [worker] ON [planning].[workerId] = [worker].[intId] AND [planning].[companyId] = [worker].[companyId]
                WHERE
                    [worker].[companyId] = 2
                    AND ([planning].[type] = 'absent' OR ([planning].[type] = 'site' AND [planning].[siteId] IN ('7710122','123456')))
               ) AS filter ON filter.[intId] = [worker].[intId] OR [worker].[intId] IN ('987654','654321')
WHERE 
    [worker].[companyId] = 2
      AND ( [planning].[id] IS NULL  OR  ( [planning].[from] <= '2014-04-30' AND [planning].[till] >= '2014-04-01') )   

答案 2 :(得分:0)

这不是一个完整的答案,但我的观点在评论中并不好,所以我会把它放在这里。

从一开始,你的大子查询似乎不对:

SELECT worker.intId 
  FROM planning
       LEFT JOIN 
       worker ON planning.workerId = worker.intId 
             AND planning.companyId = worker.companyId
 WHERE worker.companyId = 2
   AND (   planning.type = 'absent' 
        OR (    planning.type = 'site' 
            AND planning.siteId IN ('7710122','123456')
           )
       )

从计划到工人的LEFT JOIN与worker.companyId = 2结合将导致INNER JOIN。

你能用语言澄清你想用子查询完成什么吗?