子查询和性能问题的聚合函数

时间:2017-02-07 22:11:00

标签: sql function subquery aggregate

我有查询,我应该从1个表中选择记录,每天插入一个表(Select Into)。对我来说这是一个很大且足够复杂的查询,因为我想要这样做1个查询。这是我想要更改的一条查询(它有许多内连接和变量分组):

Select  RIGHT('0'+LTRIM(DATEDIFF(MINUTE,MIN(CASE WHEN [EnteranceDevice] IN(1) 
THEN CAST(EventDate as datetime) ELSE NULL END),(Select Cast([Start] as time) 
as Start FROM [dbo].[Period] Where strDay=DATEPART(dw,CAST('2017-01-30' as date)) 
And Timezone=[dbo].[Timezone].Timezone))/60),2) +':'+ 
RIGHT('0'+LTRIM(DATEDIFF(MINUTE,MIN(CASE WHEN [EnteranceDevice] IN(1) 
THEN CAST(EventDate as datetime) ELSE NULL END),(Select Cast([Start] as time) as Start 
FROM [dbo].[Period] Where strDay=DATEPART(dw,CAST('2017-01-30' as date)) 
And Timezone=[Timezone].Timezone))%60),2) AS WorkingHours from  [dbo].[Events]

此查询有效,它会在01:25时给出答案。当我想将[EnteranceDevice] IN(1)更改为[EnteranceDevice] IN(从[SPS]。[dbo] .Users中选择ReaderInput时),它给出“无法对包含聚合或子查询的表达式执行聚合函数”错误

  1. 我该如何解决这个问题?
  2. ReaderInput(nvarchar(50))具有这样的值(在1记录中)'1,3,5',因为它应该存储多于1个设备ID但EnteranceDevice是int。那么Casting(Cast(EnteranceDevice as nvarchar(50)) IN(...))会起作用吗?
  3. 我确信您在我的代码中看到了许多性能问题。我想听听有关查询的建议。

1 个答案:

答案 0 :(得分:0)

记得......说些什么是"在"与左连接和目标不为空相同,因此重构很简单,如下所示:

无法读取您的代码必须重新格式化它以获得某种逻辑....

Select  
  RIGHT(
    '0'+LTRIM(DATEDIFF(MINUTE,MIN(CASE WHEN [EnteranceDevice] IN(1) THEN CAST(EventDate as datetime) ELSE NULL END),
    (Select Cast([Start] as time) as Start FROM [dbo].[Period] Where strDay=DATEPART(dw,CAST('2017-01-30' as date)) And Timezone=[dbo].[Timezone].Timezone))/60),
    2
  ) +
  ':'+ 
  RIGHT(
    '0'+LTRIM(DATEDIFF(MINUTE,MIN(CASE WHEN [EnteranceDevice] IN(1) THEN CAST(EventDate as datetime) ELSE NULL END),
    (Select Cast([Start] as time) as Start FROM [dbo].[Period] Where strDay=DATEPART(dw,CAST('2017-01-30' as date)) And Timezone=[Timezone].Timezone))%60),
  2) AS WorkingHours 
from  [dbo].[Events]

首先,您有两次相同的子查询。把它拉成交叉连接

Select  
  RIGHT('0'+LTRIM(DATEDIFF(MINUTE,MIN(CASE WHEN [EnteranceDevice] IN(1) THEN CAST(EventDate as datetime) ELSE NULL END),x.start)/60),2) +
  ':'+ 
  RIGHT('0'+LTRIM(DATEDIFF(MINUTE,MIN(CASE WHEN [EnteranceDevice] IN(1) THEN CAST(EventDate as datetime) ELSE NULL END),x.start)%60),2) AS WorkingHours 
from  [dbo].[Events]
cross join (
  Select Cast([Start] as time) as Start 
  FROM [dbo].[Period] 
  Where strDay=DATEPART(dw,CAST('2017-01-30' as date)) 
    And Timezone=[Timezone].Timezone
) x

现在加入用户并检查null

Select  
  RIGHT('0'+LTRIM(DATEDIFF(MINUTE,MIN(CASE WHEN u.ReaderInput is not null THEN CAST(EventDate as datetime) ELSE NULL END),x.start)/60),2) +
  ':'+ 
  RIGHT('0'+LTRIM(DATEDIFF(MINUTE,MIN(CASE WHEN u.ReaderInput is not null THEN CAST(EventDate as datetime) ELSE NULL END),x.start)%60),2) AS WorkingHours 
from  [dbo].[Events]
left join [SPS].[dbo].Users u on [EnteranceDevice] = u.ReaderInput
cross join (
  Select Cast([Start] as time) as Start 
  FROM [dbo].[Period] 
  Where strDay=DATEPART(dw,CAST('2017-01-30' as date)) 
    And Timezone=[Timezone].Timezone
) x