Форум программистов, компьютерный форум, киберфорум
Microsoft SQL Server
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/6: Рейтинг темы: голосов - 6, средняя оценка - 4.83
5 / 5 / 1
Регистрация: 11.02.2013
Сообщений: 238

Оптимизация запроса

24.04.2013, 10:20. Показов 1166. Ответов 7
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день, уважаемые форумчане. Возникла потребности оптимизировать по производительности некоторые куски своего запроса.

Так, например, есть некоторая функция, которая в качестве результата выводит количество дней в текущем месяце, удовлетворяющих некоторым условиям. В теле селекта функции вот такая вот сумма

T-SQL
1
2
3
(CASE WHEN (1 NOT IN (SELECT day(ONDATE) FROM Axon.fep.dbo.HOLIDAYS WHERE month(ONDATE) = @MONTH and year(ONDATE) = @YEAR) ) and 1 <= @TODAY-1 and (@Day_1 < @PEAK*@demandSoFarThisMonth/@WORKDAYS_BEFORE_TODAY)  THEN 1 ELSE 0 END) +      
..............
(CASE WHEN (30 NOT IN (SELECT day(ONDATE) FROM Axon.fep.dbo.HOLIDAYS WHERE month(ONDATE) = @MONTH and year(ONDATE) = @YEAR) ) and 30 <= @TODAY-1 and (@Day_30 < @PEAK*@demandSoFarThisMonth/@WORKDAYS_BEFORE_TODAY)  THEN 1 ELSE 0 END)

Axon.fep.dbo.HOLIDAYS - табличка, содержащая перечень нерабочих дней (формат datetime),

T-SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
DECLARE @TODAY real
SET @TODAY = day(getdate())
 
DECLARE @MONTH real
SET @MONTH = month(getdate())
 
DECLARE @YEAR real
SET @YEAR = year(getdate())
 
DECLARE @PEAK real
SET @PEAK = 1.5
 
DECLARE @WORKDAYS_BEFORE_TODAY real
SET @WORKDAYS_BEFORE_TODAY = 1
 
BEGIN
    IF day(getdate()) = 1
    SET @WORKDAYS_BEFORE_TODAY = 0.001 
 
    IF day(getdate()) > 1 
    SELECT @WORKDAYS_BEFORE_TODAY = @TODAY - count(*) - 1   
        FROM [FEP].[dbo].[Holidays] WHERE day(ondate) <= @TODAY and month(ondate) = month(getdate()) and    year(ondate)= year(getdate())  
END
Все остальное - параметры входящих полей
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
24.04.2013, 10:20
Ответы с готовыми решениями:

Оптимизация запроса
Добрый день, имеется БД с числом записей в raspis_service примерно 50 записей, во всех остальных таблицах число записей больше 500 000. ...

Оптимизация запроса
/*Таблица документов*/ Declare @Documents Table( orID int, repID int, DocTypeID int, repIDD nvarchar(100), Condition int ...

Оптимизация запроса
На клиентской части данный запрос отрабатывает больше минуты. Как его оптимизировать: select distinct *, ...

7
1313 / 945 / 144
Регистрация: 17.01.2013
Сообщений: 2,348
24.04.2013, 12:39
можно такой вариант попробовать, может быстрее, может медленнее...)
Кликните здесь для просмотра всего текста
T-SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
;with 
Holidays(ondate) as 
   (select GETDATE()-2 union all select GETDATE()-5),
Days as (
   select Day=6*i+j
   from (values(0),(1),(2),(3),(4),(5))i(i)
   cross join (values(1),(2),(3),(4),(5),(6))j(j)
   ),
WORKDAYS_BEFORE_TODAY as (
   SELECT Workdays_Before_Today=COUNT(*)
   FROM days d
   cross apply (select First_Day=DATEADD(DAY,1-DAY(GETDATE()),GETDATE())) first_day
   cross apply (select Last_Day=DATEADD(DAY,-1,DATEADD(MONTH,1,first_day))) last_day
   left join Holidays h on ondate between First_Day and Last_Day and DAY(h.ondate)=d.Day
   where d.Day<=DAY(GETDATE()) and h.ondate is null
   )
select SUM(Quantity)
from days d
cross apply (select Workdays_Before_Today from WORKDAYS_BEFORE_TODAY ) WORKDAYS 
cross apply (select 
   Today=day(GETDATE()),
   Koeff=@PEAK*@demandSoFarThisMonth/ISNULL(NULLIF(Workdays_Before_Today,0),1)-- защита от деления на 0
   ) TODAY
cross apply (select Quantity=case 
   when d.day=01 and @Day_1 < Koeff then 1 
   when d.day=02 and @Day_2 < Koeff then 1 
   when d.day=03 and @Day_3 < Koeff then 1 
   when d.day=04 and @Day_4 < Koeff then 1 
   when d.day=05 and @Day_5 < Koeff then 1 
   when d.day=06 and @Day_6 < Koeff then 1 
   when d.day=07 and @Day_7 < Koeff then 1 
   when d.day=08 and @Day_8 < Koeff then 1 
   when d.day=09 and @Day_9 < Koeff then 1 
   when d.day=10 and @Day_10< Koeff then 1 
   when d.day=11 and @Day_11< Koeff then 1 
   when d.day=12 and @Day_12< Koeff then 1 
   when d.day=13 and @Day_13< Koeff then 1 
   when d.day=14 and @Day_14< Koeff then 1 
   when d.day=15 and @Day_15< Koeff then 1 
   when d.day=16 and @Day_16< Koeff then 1 
   when d.day=17 and @Day_17< Koeff then 1 
   when d.day=18 and @Day_18< Koeff then 1 
   when d.day=19 and @Day_19< Koeff then 1 
   when d.day=20 and @Day_20< Koeff then 1 
   when d.day=21 and @Day_21< Koeff then 1 
   when d.day=22 and @Day_22< Koeff then 1 
   when d.day=23 and @Day_23< Koeff then 1 
   when d.day=24 and @Day_24< Koeff then 1 
   when d.day=25 and @Day_25< Koeff then 1 
   when d.day=26 and @Day_26< Koeff then 1 
   when d.day=27 and @Day_27< Koeff then 1 
   when d.day=28 and @Day_28< Koeff then 1 
   when d.day=29 and @Day_29< Koeff then 1 
   when d.day=30 and @Day_30< Koeff then 1 
   when d.day=31 and @Day_31< Koeff then 1 
   else 0 end) c
where d.Day<=Today
1
5 / 5 / 1
Регистрация: 11.02.2013
Сообщений: 238
24.04.2013, 14:57  [ТС]
Этот селект должен сидеть в функции, поэтому использование встроенных функций невозможно

Добавлено через 2 минуты
Да, забыл отметить, что использую кросс-платформу из двух серверов 2000 и 2008, поэтому операторы типа cross apply также не подходят. Но в любом случае, спасибо за Ваш вариант!
0
1313 / 945 / 144
Регистрация: 17.01.2013
Сообщений: 2,348
24.04.2013, 15:22
Ну идеи-то можно портировать и в sql2000
1) select from Holidays where ondate between начало_месяца and getdate() - позволит включить индекс по ondate
2) отдельная таблица из 31 дня, к которой left join Holidays (с учетом п.1) и где where Holidays.ondate is null
то есть все дни, которых нет в Holidays - рабочие
ЯТД, это лучше, чем 30 раз сканировать всю таблицу выходных
3) для оптимизации производительности лучше всего отказаться от использования UDF (по возможности)

Добавлено через 1 минуту
Цитата Сообщение от Lelik83 Посмотреть сообщение
...в функции ... использование встроенных функций невозможно
Можно ссылку, где это написано?
0
5 / 5 / 1
Регистрация: 11.02.2013
Сообщений: 238
24.04.2013, 15:24  [ТС]
А что такое ЯТД и UDF?
0
1313 / 945 / 144
Регистрация: 17.01.2013
Сообщений: 2,348
24.04.2013, 15:25
я так думаю, это user defined function
0
5 / 5 / 1
Регистрация: 11.02.2013
Сообщений: 238
24.04.2013, 15:26  [ТС]
...
0
1313 / 945 / 144
Регистрация: 17.01.2013
Сообщений: 2,348
24.04.2013, 16:59
Кликните здесь для просмотра всего текста
SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
-- if object_id('Days') is not null drop table Days
IF object_id('Days') IS NULL BEGIN
   CREATE TABLE Days (DAY INT)
   INSERT Days SELECT NUMBER FROM master..spt_values WHERE TYPE='P' AND NUMBER BETWEEN 1 AND 31
   SELECT * FROM Days
END
GO
 
ALTER 
FUNCTION [dbo].[Q_days](
   @PEAK REAL, @TODAY datetime, @WORKDAYS_BEFORE_TODAY REAL, @demandSoFarThisMonth INT,
   @Day_1 INT, @Day_2 INT, @Day_3 INT, @Day_4 INT, @Day_5 INT, @Day_6 INT, @Day_7 INT, @Day_8 INT, @Day_9 INT, @Day_10 INT,
   @Day_11 INT, @Day_12 INT, @Day_13 INT, @Day_14 INT, @Day_15 INT, @Day_16 INT, @Day_17 INT, @Day_18 INT, @Day_19 INT, @Day_20 INT,
   @Day_21 INT, @Day_22 INT, @Day_23 INT, @Day_24 INT, @Day_25 INT, @Day_26 INT, @Day_27 INT, @Day_28 INT, @Day_29 INT, @Day_30 INT, @Day_31 INT)
RETURNS REAL /*char(6)*/ AS
BEGIN
   /*
   select @WORKDAYS_BEFORE_TODAY=isnull(nullif(count(*),0),0.001)
   from days d
   left join Holidays h on 
      h.ondate between dateadd(day,1-day(@TODAY),@TODAY) and @TODAY
      and day(ondate)=d.day
   where d.day<=day(@TODAY) and h.ondate is null
   */
   DECLARE @koeff REAL
   SELECT @koeff=@PEAK*@demandSoFarThisMonth/@WORKDAYS_BEFORE_TODAY
   
   DECLARE @rv REAL /*char(6)*/
   SELECT @rv=SUM(CASE
      WHEN d.day=01 AND @Day_1 < @Koeff THEN 1 
      WHEN d.day=02 AND @Day_2 < @Koeff THEN 1 
      WHEN d.day=03 AND @Day_3 < @Koeff THEN 1 
      WHEN d.day=04 AND @Day_4 < @Koeff THEN 1 
      WHEN d.day=05 AND @Day_5 < @Koeff THEN 1 
      WHEN d.day=06 AND @Day_6 < @Koeff THEN 1 
      WHEN d.day=07 AND @Day_7 < @Koeff THEN 1 
      WHEN d.day=08 AND @Day_8 < @Koeff THEN 1 
      WHEN d.day=09 AND @Day_9 < @Koeff THEN 1 
      WHEN d.day=10 AND @Day_10< @Koeff THEN 1 
      WHEN d.day=11 AND @Day_11< @Koeff THEN 1 
      WHEN d.day=12 AND @Day_12< @Koeff THEN 1 
      WHEN d.day=13 AND @Day_13< @Koeff THEN 1 
      WHEN d.day=14 AND @Day_14< @Koeff THEN 1 
      WHEN d.day=15 AND @Day_15< @Koeff THEN 1 
      WHEN d.day=16 AND @Day_16< @Koeff THEN 1 
      WHEN d.day=17 AND @Day_17< @Koeff THEN 1 
      WHEN d.day=18 AND @Day_18< @Koeff THEN 1 
      WHEN d.day=19 AND @Day_19< @Koeff THEN 1 
      WHEN d.day=20 AND @Day_20< @Koeff THEN 1 
      WHEN d.day=21 AND @Day_21< @Koeff THEN 1 
      WHEN d.day=22 AND @Day_22< @Koeff THEN 1 
      WHEN d.day=23 AND @Day_23< @Koeff THEN 1 
      WHEN d.day=24 AND @Day_24< @Koeff THEN 1 
      WHEN d.day=25 AND @Day_25< @Koeff THEN 1 
      WHEN d.day=26 AND @Day_26< @Koeff THEN 1 
      WHEN d.day=27 AND @Day_27< @Koeff THEN 1 
      WHEN d.day=28 AND @Day_28< @Koeff THEN 1 
      WHEN d.day=29 AND @Day_29< @Koeff THEN 1 
      WHEN d.day=30 AND @Day_30< @Koeff THEN 1 
      WHEN d.day=31 AND @Day_31< @Koeff THEN 1 
      ELSE 0 END)
   FROM days d
   LEFT JOIN Holidays h ON 
      h.ondate BETWEEN dateadd(DAY,1-DAY(@TODAY),@TODAY) AND @TODAY
      AND DAY(ondate)=d.day
   WHERE d.day<=DAY(@TODAY) AND h.ondate IS NULL
   
   RETURN @rv
END
GO
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
24.04.2013, 16:59
Помогаю со студенческими работами здесь

Оптимизация запроса
Подскажите, возможно ли в данном случае оптимизировать сам запрос. Красота и идеологические аспекты не интересуют, только скорость...

Оптимизация запроса
Есть ли возможность существенно сократить время запроса? Не обязательно выжимать последние капли скорости, но сокращение времени запроса...

Оптимизация запроса
Добрый день, подскажите, пожалуйста: Имеется таблица с данными пользователей: CREATE TABLE Users ( UserID uniqueidentifier NOT NULL...

Оптимизация SQL запроса
есть запрос select ... тут поля ( select field1, field2, (field1/field2) as res from (Select DISTINCT count(1) as...

Оптимизация sql-запроса с Count()
Добрый день! Имеется таблица Table1 --id int primary key identity(1,1) --UserIP varchar(15) - айпишники --PageURL varchar(500) урлы...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
8
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru