#sql #sql-server #sql-server-2008 #stored-procedures #parameters
#sql #sql-сервер #sql-server-2008 #хранимые процедуры #параметры
Вопрос:
Я создаю хранимые процедуры для создания отчетов на основе пользовательских параметров в качестве фильтров. У меня уже работает почти каждый SELECT
запрос, но последний, который содержит кучу LEFT JOIN
, заканчивается возвратом NULL
во всей таблице.
Я выполняю хранимую процедуру следующим образом:
exec promediosDot
@periodo1a = 201612,
@periodo1b = 201703,
@periodo2a = 201712,
@periodo2b = 201803,
@periodo3a = 201812,
@periodo3b = 201903,
@tipGas = 'VENTAS'
Это запрос:
CREATE PROCEDURE promediosDot
@periodo1a INT,
@periodo1b INT,
@periodo2a INT,
@periodo2b INT,
@periodo3a INT,
@periodo3b INT,
@tipGas NVARCHAR(6)
AS
SELECT DISTINCT
T1.HOMOLOG_VP,
PROMEDIO1 = ((T2.CANT_PERS1 T3.CANT_PERS2 T4.CANT_PERS3 T5.CANT_PERS4) / 4),
PROMEDIO2 = ((T6.CANT_PERS1 T7.CANT_PERS2 T8.CANT_PERS3 T9.CANT_PERS4) / 4),
PROMEDIO3 = ((T10.CANT_PERS1 T11.CANT_PERS2 T12.CANT_PERS3 T13.CANT_PERS4) / 4)
FROM
(SELECT *
FROM USOS_CP
WHERE PER_PRO > 201611) T1
LEFT JOIN
(SELECT
HOMOLOG_VP,
COUNT(DISTINCT ID_HR) AS CANT_PERS1
FROM
DOTACION
WHERE
PERPRO = @periodo1a
GROUP BY
HOMOLOG_VP) T2 ON T1.HOMOLOG_VP = T2.HOMOLOG_VP
LEFT JOIN
(SELECT
HOMOLOG_VP, COUNT(DISTINCT ID_HR) AS CANT_PERS2
FROM
DOTACION
WHERE
PERPRO = @periodo1a 1
GROUP BY
HOMOLOG_VP) T3 ON T1.HOMOLOG_VP = T3.HOMOLOG_VP
LEFT JOIN
(SELECT
HOMOLOG_VP, COUNT(DISTINCT ID_HR) AS CANT_PERS3
FROM
DOTACION
WHERE
PERPRO = @periodo1a 2
GROUP BY
HOMOLOG_VP) T4 ON T1.HOMOLOG_VP = T4.HOMOLOG_VP
LEFT JOIN
(SELECT
HOMOLOG_VP, COUNT(DISTINCT ID_HR) AS CANT_PERS4
FROM
DOTACION
WHERE
PERPRO = @periodo1a 3
GROUP BY
HOMOLOG_VP) T5 ON T1.HOMOLOG_VP = T5.HOMOLOG_VP
--
LEFT JOIN
(SELECT
HOMOLOG_VP, COUNT(DISTINCT ID_HR) AS CANT_PERS1
FROM
DOTACION
WHERE
PERPRO = @periodo2a
GROUP BY
HOMOLOG_VP) T6 ON T1.HOMOLOG_VP = T6.HOMOLOG_VP
LEFT JOIN
(SELECT
HOMOLOG_VP, COUNT(DISTINCT ID_HR) AS CANT_PERS2
FROM
DOTACION
WHERE
PERPRO = @periodo2a 1
GROUP BY
HOMOLOG_VP) T7 ON T1.HOMOLOG_VP = T7.HOMOLOG_VP
LEFT JOIN
(SELECT
HOMOLOG_VP, COUNT(DISTINCT ID_HR) AS CANT_PERS3
FROM
DOTACION
WHERE
PERPRO = @periodo2a 2
GROUP BY
HOMOLOG_VP) T8 ON T1.HOMOLOG_VP = T8.HOMOLOG_VP
LEFT JOIN
(SELECT
HOMOLOG_VP, COUNT(DISTINCT ID_HR) AS CANT_PERS4
FROM
DOTACION
WHERE
PERPRO = @periodo2a 3
GROUP BY
HOMOLOG_VP) T9 ON T1.HOMOLOG_VP = T9.HOMOLOG_VP
--
LEFT JOIN
(SELECT
HOMOLOG_VP, COUNT(DISTINCT ID_HR) AS CANT_PERS1
FROM
DOTACION
WHERE
PERPRO = @periodo3a
GROUP BY
HOMOLOG_VP) T10 ON T1.HOMOLOG_VP = T10.HOMOLOG_VP
LEFT JOIN
(SELECT
HOMOLOG_VP, COUNT(DISTINCT ID_HR) AS CANT_PERS2
FROM
DOTACION
WHERE
PERPRO = @periodo3a 1
GROUP BY
HOMOLOG_VP) T11 ON T1.HOMOLOG_VP = T11.HOMOLOG_VP
LEFT JOIN
(SELECT
HOMOLOG_VP, COUNT(DISTINCT ID_HR) AS CANT_PERS3
FROM
DOTACION
WHERE
PERPRO = @periodo3a 2
GROUP BY
HOMOLOG_VP) T12 ON T1.HOMOLOG_VP = T12.HOMOLOG_VP
LEFT JOIN
(SELECT
HOMOLOG_VP, COUNT(DISTINCT ID_HR) AS CANT_PERS4
FROM
DOTACION
WHERE
PERPRO = @periodo3a 3
GROUP BY
HOMOLOG_VP) T13 ON T1.HOMOLOG_VP = T13.HOMOLOG_VP
GO
Результаты (извлечение):
HOMOLOG_VP PROMEDIO1 PROMEDIO2 PROMEDIO3
---------------------------------------------
a3 NULL NULL NULL
a4 NULL NULL NULL
Я не уверен, что это просто природа параметров, которые не работают до определенного момента или не работают над вложенным запросом. Запрос работает отлично, если параметры записываются вручную. Любая помощь приветствуется.
Комментарии:
1. Черт возьми, похоже, что это можно было бы значительно упростить. Это может быть один запрос с несколькими сводными столбцами и выражением case.
Ответ №1:
Проблема может возникнуть из-за того, что ваш период установлен на декабрь как 201612, и если вы добавите его, он станет 201613 вместо 201701. Это проблема использования целых чисел для значений даты. Как упоминал Шон, это также можно преобразовать в более простой запрос.
CREATE PROCEDURE promediosDot
@periodo1a int,
@periodo1b int,
@periodo2a int,
@periodo2b int,
@periodo3a int,
@periodo3b int,
@tipGas nvarchar(6)
AS
SELECT
U.HOMOLOG_VP,
PROMEDIO1 = ( COUNT(DISTINCT CASE WHEN D.PERPRO = CONVERT( CHAR(6), DATEADD( MM, 0, CAST( @periodo1a AS VARCHAR(8)) '01'), 112) THEN D.ID_HR END)
COUNT(DISTINCT CASE WHEN D.PERPRO = CONVERT( CHAR(6), DATEADD( MM, 1, CAST( @periodo1a AS VARCHAR(8)) '01'), 112) THEN D.ID_HR END)
COUNT(DISTINCT CASE WHEN D.PERPRO = CONVERT( CHAR(6), DATEADD( MM, 2, CAST( @periodo1a AS VARCHAR(8)) '01'), 112) THEN D.ID_HR END)
COUNT(DISTINCT CASE WHEN D.PERPRO = CONVERT( CHAR(6), DATEADD( MM, 3, CAST( @periodo1a AS VARCHAR(8)) '01'), 112) THEN D.ID_HR END)) /4,
PROMEDIO2 = ( COUNT(DISTINCT CASE WHEN D.PERPRO = CONVERT( CHAR(6), DATEADD( MM, 0, CAST( @periodo2a AS VARCHAR(8)) '01'), 112) THEN D.ID_HR END)
COUNT(DISTINCT CASE WHEN D.PERPRO = CONVERT( CHAR(6), DATEADD( MM, 1, CAST( @periodo2a AS VARCHAR(8)) '01'), 112) THEN D.ID_HR END)
COUNT(DISTINCT CASE WHEN D.PERPRO = CONVERT( CHAR(6), DATEADD( MM, 2, CAST( @periodo2a AS VARCHAR(8)) '01'), 112) THEN D.ID_HR END)
COUNT(DISTINCT CASE WHEN D.PERPRO = CONVERT( CHAR(6), DATEADD( MM, 3, CAST( @periodo2a AS VARCHAR(8)) '01'), 112) THEN D.ID_HR END)) /4,
PROMEDIO3 = ( COUNT(DISTINCT CASE WHEN D.PERPRO = CONVERT( CHAR(6), DATEADD( MM, 0, CAST( @periodo3a AS VARCHAR(8)) '01'), 112) THEN D.ID_HR END)
COUNT(DISTINCT CASE WHEN D.PERPRO = CONVERT( CHAR(6), DATEADD( MM, 1, CAST( @periodo3a AS VARCHAR(8)) '01'), 112) THEN D.ID_HR END)
COUNT(DISTINCT CASE WHEN D.PERPRO = CONVERT( CHAR(6), DATEADD( MM, 2, CAST( @periodo3a AS VARCHAR(8)) '01'), 112) THEN D.ID_HR END)
COUNT(DISTINCT CASE WHEN D.PERPRO = CONVERT( CHAR(6), DATEADD( MM, 3, CAST( @periodo3a AS VARCHAR(8)) '01'), 112) THEN D.ID_HR END)) /4
FROM USOS_CP U
JOIN DOTACION D ON U.HOMOLOG_VP = D.HOMOLOG_VP
WHERE U.PER_PRO > 201611
AND (D.PERPRO BETWEEN @periodo1a AND @periodo1a 3
OR D.PERPRO BETWEEN @periodo2a AND @periodo2a 3
OR D.PERPRO BETWEEN @periodo3a AND @periodo3a 3)
GROUP BY U.HOMOLOG_VP
ORDER BY HOMOLOG_VP;
Комментарии:
1. Не видел этого в моем коде, ваш код работает отлично. Спасибо!
2. Нет проблем. Я надеюсь, что вы поняли, что я забыл изменить вычисление в предложении WHERE .
Ответ №2:
У вас есть несколько параметров, которые не используются в опубликованном вами коде. Но вы могли бы значительно упростить этот запрос. Что-то вроде этого должно быть то же самое. Нет необходимости снова и снова присоединяться к одной и той же таблице.
SELECT cp.HOMOLOG_VP
, PROMEDIO1 = count(case when d.PERPRO >= @periodo1a and d.PERPRO <= @periodo1a 3 then 1 end) / 4
, PROMEDIO2 = count(case when d.PERPRO >= @periodo2a and d.PERPRO <= @periodo2a 3 then 1 end) / 4
, PROMEDIO3 = count(case when d.PERPRO >= @periodo3a and d.PERPRO <= @periodo3a 3 then 1 end) / 4
FROM USOS_CP cp
left join DOTACION d on d.HOMOLOG_VP = cp.HOMOLOG_VP
WHERE cp.PER_PRO > 201611
group by cp.HOMOLOG_VP
Комментарии:
1. Я думал сделать что-то подобное, но я не уверен, что это сработает, потому что OP использует COUNT DISTINCT .
2. Да, у процедуры есть еще 2 запроса, которые используют эти переменные после того, который я опубликовал. Я знаю, что мой запрос — это мусор, но мне нужно каждый раз различать идентификаторы (период), а также ваши циклы вечно.
3. Не удалось протестировать это, потому что мы не получили определения таблиц или образцы данных. Это был мой выстрел в темноте. Ну что ж… в следующий раз опубликуйте определения таблиц, и людям будет легче помочь.