2017-02-07 2 views
0

У меня есть запрос, который я должен выбрать записи из 1 таблицы, чтобы каждый раз вставлять другую таблицу (выберите «В»). Это большой и достаточно сложный запрос для меня из-за того, что я хочу сделать это 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 (выберите ReaderInput из [SPS]. [Dbo] .Users), он дает «Невозможно выполнить агрегированную функцию в выражении, содержащем агрегат или подзапрос»

  1. Как я могу решить эту проблему?
  2. ReaderInput (nvarchar (50)) имеет такие значения (в 1 записи) '1,3,5', потому что он должен хранить более одного идентификатора устройства, а EnteranceDevice - int. Итак, Casting (Cast(EnteranceDevice as nvarchar(50)) IN(...)) будет работать?
  3. Я уверен, что вы видите много проблем с производительностью в моем коде. Я хочу услышать рекомендации по запросу.

ответ

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 

Теперь присоединиться к пользователям и проверить нулевой

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 
+0

спасибо за быстрый ответ. Я исправлю все два запроса. И есть что-то о [EnteranceDevice] и [ReaderInput]. [EnteranceDevice] - int, и он получает целые числа, такие как 1,2,4,6 и т. Д. И [ReaderInput] - nvarchar (50), и он может иметь значения как «2,3,5» или просто «4». Итак, CASE WHEN [EnteranceDevice] iS NOT NULL будет достаточно? Из-за значения EnteranceDevice должно быть в столбце ReaderInput. – Murat

+0

не уверен, вероятно, если '[EnteranceDevice] = u.ReaderInput' не сравнивает одни и те же типы, то одна сторона должна была бы перейти на другой тип. Это не очень распространено - они должны быть одного типа или что-то очень не так с вашим дизайном. – Hogan

Смежные вопросы