- 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
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
ALTER PROCEDURE [dbo].[prodam_Получить_Начисления_По_ЛС]
@кодЛС uniqueidentifier,
@дата date,
@источникНачислений nvarchar(50)
AS
BEGIN
SET NOCOUNT ON;
IF @источникНачислений = 'AccountCharge_Lain'
BEGIN
SELECT
CAST(MONTH(@дата) as nvarchar(2))+'.'+CAST(YEAR(@дата) as nvarchar(4)) as 'Расчетный период'
,ach.ID as 'Начисление'
,suc.Title as 'Услуга'
,ach.[Formula] as 'Формула'
,ach.[FormulaWithValues] as 'Формула со значениями'
,CAST(ach.[SumOfPaymentEnteredTheLastMonth] as decimal(19,2)) as 'Оплаты поступившие в предыдущем месяце (руб.)'
,CAST(ach.[SumOfRecalculationForTheLastMonth]as decimal(19,2)) as 'Перерасчет за предыдущий период (руб.)'
,CAST(ach.[SumOfDebtOrOverpayment]as decimal(19,2)) as 'Долг (+), переплата (-) (руб.)'
,um.Title as 'Единица измерения (по нормативу / приборам учета)'
,CAST(ach.[SumOfTariffForUnitOfService]as decimal(19,2)) as 'Тариф за единицу услуги (руб.)'
,CAST(ach.[SumOfChargeForMonthUnderTheTariff]as decimal(19,2)) as 'Начислено за месяц по тарифу (руб.)'
,CAST(ach.[SumOfShortShipmentOfService]as decimal(19,2)) as 'Сумма недопоставки (руб.)'
,CAST(ach.[SumOfPaymentInViewOfShortShipment]as decimal(19,2)) as 'Начислено к оплате с учетом недопоставки (руб.)'
,CAST(ach.[AmountOfDaysOfShortShipmentOfService]as decimal(19,2)) as 'Недопоставка услуг (дней)'
,suc.ID as 'ID'
FROM
[RegionDBNew].[dbo].Account acc
INNER JOIN [RegionDBNew].[dbo].[AccountCharge_Lain] ach ON
ach.CalculationYear = YEAR(@дата) AND
ach.CalculationMonth = MONTH(@дата) AND
ach.AccountID = acc.ID
LEFT JOIN [RegionDBNew].[dbo].UnitOfMeasure um ON ach.[UnitOfMeasureID] = um.ID
LEFT JOIN [RegionDBNew].[dbo].[ServiceUnderAccount] suc ON suc.ID = ach.ServiceUnderAccountID
WHERE
acc.ID = @кодЛС
ORDER BY
suc.Title;
END
ELSE IF @источникНачислений = 'AccountCharge_Prodam'
BEGIN
SELECT
CAST(MONTH(@дата) as nvarchar(2))+'.'+CAST(YEAR(@дата) as nvarchar(4)) as 'Расчетный период'
,ach.ID as 'Начисление'
,suc.Title as 'Услуга'
,ach.[Formula] as 'Формула'
,ach.[FormulaWithValues] as 'Формула со значениями'
,CAST(ach.[SumOfPaymentEnteredTheLastMonth] as decimal(19,2)) as 'Оплаты поступившие в предыдущем месяце (руб.)'
,CAST(ach.[SumOfRecalculationForTheLastMonth] as decimal(19,2)) as 'Перерасчет за предыдущий период (руб.)'
,CAST(ach.[SumOfDebtOrOverpayment] as decimal(19,2)) as 'Долг (+), переплата (-) (руб.)'
,um.Title as 'Единица измерения (по нормативу / приборам учета)'
,CAST(ach.[SumOfTariffForUnitOfService] as decimal(19,2)) as 'Тариф за единицу услуги (руб.)'
,CAST(ach.[SumOfChargeForMonthUnderTheTariff] as decimal(19,2)) as 'Начислено за месяц по тарифу (руб.)'
,CAST(ach.[SumOfShortShipmentOfService] as decimal(19,2)) as 'Сумма недопоставки (руб.)'
,CAST(ach.[SumOfPaymentInViewOfShortShipment] as decimal(19,2)) as 'Начислено к оплате с учетом недопоставки (руб.)'
,CAST(ach.[AmountOfDaysOfShortShipmentOfService] as decimal(19,2)) as 'Недопоставка услуг (дней)'
,suc.ID as 'ID'
FROM
[RegionDBNew].[dbo].Account acc
INNER JOIN [RegionDBNew].[dbo].[AccountCharge_Prodam] ach ON
ach.CalculationYear = YEAR(@дата) AND
ach.CalculationMonth = MONTH(@дата) AND
ach.AccountID = acc.ID
LEFT JOIN [RegionDBNew].[dbo].UnitOfMeasure um ON ach.[UnitOfMeasureID] = um.ID
LEFT JOIN [RegionDBNew].[dbo].[ServiceUnderAccount] suc ON suc.ID = ach.ServiceUnderAccountID
WHERE
acc.ID = @кодЛС
ORDER BY
suc.Title;
END
ELSE IF @источникНачислений = 'AccountCharge'
BEGIN
SELECT
CAST(MONTH(@дата) as nvarchar(2))+'.'+CAST(YEAR(@дата) as nvarchar(4)) as 'Расчетный период'
,ach.ID as 'Начисление'
,suc.Title as 'Услуга'
,ach.[Formula] as 'Формула'
,ach.[FormulaWithValues] as 'Формула со значениями'
,CAST(ach.[SumOfPaymentEnteredTheLastMonth] as decimal(19,2)) as 'Оплаты поступившие в предыдущем месяце (руб.)'
,CAST(ach.[SumOfRecalculationForTheLastMonth] as decimal(19,2)) as 'Перерасчет за предыдущий период (руб.)'
,CAST(ach.[SumOfDebtOrOverpayment] as decimal(19,2)) as 'Долг (+), переплата (-) (руб.)'
,um.Title as 'Единица измерения (по нормативу / приборам учета)'
,CAST(ach.[SumOfTariffForUnitOfService] as decimal(19,2)) as 'Тариф за единицу услуги (руб.)'
,CAST(ach.[SumOfChargeForMonthUnderTheTariff] as decimal(19,2)) as 'Начислено за месяц по тарифу (руб.)'
,CAST(ach.[SumOfShortShipmentOfService] as decimal(19,2)) as 'Сумма недопоставки (руб.)'
,CAST(ach.[SumOfPaymentInViewOfShortShipment] as decimal(19,2)) as 'Начислено к оплате с учетом недопоставки (руб.)'
,CAST(ach.[AmountOfDaysOfShortShipmentOfService] as decimal(19,2)) as 'Недопоставка услуг (дней)'
,suc.ID as 'ID'
FROM
[RegionDBNew].[dbo].Account acc
INNER JOIN [RegionDBNew].[dbo].[AccountCharge] ach ON
ach.CalculationYear = YEAR(@дата) AND
ach.CalculationMonth = MONTH(@дата) AND ach.CalculationMonth = MONTH(@дата) AND
ach.AccountID = acc.ID
LEFT JOIN [RegionDBNew].[dbo].UnitOfMeasure um ON ach.[UnitOfMeasureID] = um.ID
LEFT JOIN [RegionDBNew].[dbo].[ServiceUnderAccount] suc ON suc.ID = ach.ServiceUnderAccountID
WHERE
acc.ID = @кодЛС
ORDER BY
suc.Title;
END
- "мкей", отвечали они и продолжали ебошить.
Даже не смешно.
>ach.CalculationMonth = MONTH(@дата) AND ach.CalculationMonth = MONTH(@дата) AND
АдЪ.
Ну и упоротые алиасы, тоже сурово.
Не продаст. Надеюсь.
- архитектура базы хромает, раз за одними и теми же полями надо лазить в 3 разные таблицы
- ужасный нейминг со смесью кириллицы и латиницы
- бизнесс-алиасы полям задаются на уровне хранимы, а не на уровне юзер-интерфейса
Из озвученного выше:
- с запятыми перед полями жить можно и даже для дебага полезно (очень легко поставив -- исключить поле из выборки. Зачем вначале запятые ставить? Чаще изменения случаются с последними элементами, а не первыми)
- 92 строку оптимизатор запросов все-равно преобразует в единое условие
Итого, как заключение - бить надо рахитектора. Разработчик выкрутился, как смог. Если разработчик этого и является рахитектором решения - бить разработчика.
Отлаживать комментированием - плохая практика.
Безусловно.
> архитектура базы хромает, раз за одними и теми же полями надо лазить в 3 разные таблицы
> Разработчик выкрутился, как смог
Можно было не копипастить - создать сводную временную таблицу или если противник temp table(о ужас!) использовать exec
Или with какой-нибудь. В ms sql давно добавили.
>[dbo].[prodam_Получить_Начисления_По_ЛС]
> @кодЛС uniqueidentifier,
> @дата date,
> @источникНачислений nvarchar(50)
Та это как в быдлоexcelе или 1C.
Да. Согласен. С точки зрения производительности оно-то оптимально, но там ошибиться просто негде.
А как такое сопровождать?
Программист оттачивает технику копипаста, и потом 16 раз такое накопировано, 32 раза итд?
>динамика - незакешированный запрос
В большинстве случаев это некритично, доли секунды на компиляцию планов стоят меньше чем труд программиста, которому потом поддерживать.
>отбросим знания with
Не надо. Они тут очень кстати.
ЗЫ Я там ошибку допустил - "незакешированный запрос" = "незакешированный план запроса", но меня поняли 😉
ЗЗЫ И все-таки не стоит думать, что все знают динамику и конструкцию with.
Это я понял.
Сборка запросов типична для ситуации когда в процедуру приходит несколько параметров @a,@b,@c,@d и нужна логика, если @a is null, то убрать условие на @a, если @b is null, то убрать джойн на @b.
Тут видится джва выхода
а) "оптимальный" копипаст на всё случаи жизни. в данном примере 16. скомпиленые планы и скорость прилагаются. проблемы возникают когда в процедуру надо добавить @e, а потом и @f.
б) OR со всеми вытекающими union и 16 сканами по таблице (t1.someA=@a or @a is null).
Тут-то на помощь и спешит динамика.