Будет ли повторно оцениваться запрос внутри ORDER BY? - PullRequest
0 голосов
/ 26 сентября 2019

У меня есть несколько объектов базы данных, которым нужно извлечь одну запись (например, TOP 1) из таблицы, но приоритет, для которого она выбрана, зависит от значения BIT в таблице настроек, и эта таблица настроек будет содержать только однустрока.

Я написал представление, которое будет выполнять необходимые функции:

CREATE VIEW TopOrganisationAddresses AS
WITH cte AS
(
    SELECT  OrganisationID,
            AddressID,
            CASE WHEN EXISTS (SELECT * FROM GlobalSettings WHERE DeliveryAddressInReports=1) THEN IsDeliveryAddress ELSE IsInvoiceAddress END AS OrderFirst,
            CASE WHEN EXISTS (SELECT * FROM GlobalSettings WHERE DeliveryAddressInReports=1) THEN IsInvoiceAddress ELSE IsDeliveryAddress END AS OrderSecond
    FROM OrganisationAddresses
)

SELECT OrganisationID, AddressID,
        ROW_NUMBER() OVER(PARTITION BY OrganisationID
                            ORDER BY OrderFirst DESC, OrderSecond DESC) AS [Row]
FROM cte

Будут ли запросы SELECT * FROM GlobalSettings оцениваться для каждого потока в таблице OrganisationAddresses? В таком случае это было бы невероятно расточительно, поскольку это только статическое значение, которое не изменится.

Ответы [ 2 ]

1 голос
/ 26 сентября 2019

SQL Server должен быть достаточно умным, чтобы выполнять запросы только один раз.Оптимизатор должен точно понимать, что вы делаете - это постоянные значения.Например, следующий запрос возвращает то же значение для id:

with cte as (
      select v.*,
             (select top 1 newid() from (values (1), (2)) v2(n) order by newid()) as val
      from (values (1), (2)) v(n)
     )
select *
from cte;

( Здесь - это db <> скрипка.)

Если вы хотитечтобы убедиться, что они вычисляются только один раз, вы можете переместить логику в предложение FROM:

CREATE VIEW TopOrganisationAddresses AS
    SELECT oa.OrganisationID, oa.AddressID,
            ROW_NUMBER() OVER (PARTITION BY oa.OrganisationID
                               ORDER BY v.OrderFirst DESC, v.OrderSecond DESC
                              ) AS [Row]
    FROM OrganisationAddresses oa CROSS JOIN
         (VALUES (CASE WHEN EXISTS (SELECT * FROM GlobalSettings WHERE DeliveryAddressInReports = 1) THEN IsDeliveryAddress ELSE IsInvoiceAddress END,,
                  CASE WHEN EXISTS (SELECT * FROM GlobalSettings WHERE DeliveryAddressInReports = 1) THEN IsInvoiceAddress ELSE IsDeliveryAddress END)
         ) v(OrderFirst, OrderSecond);
1 голос
/ 26 сентября 2019

Теоретически это может быть оптимизировано, но вы можете просто использовать другой cte, который делает это SELECT, чтобы гарантировать его, например

CREATE VIEW TopOrganisationAddresses AS
WITH cteg AS 
(
    SELECT CASE WHEN EXISTS (SELECT * FROM GlobalSettings WHERE DeliveryAddressInReports=1) THEN 1 ELSE 0 END AS dair
),
cte AS
(
    SELECT  OrganisationID,
            AddressID,
            CASE WHEN cteg.dair = 1 THEN IsDeliveryAddress ELSE IsInvoiceAddress END AS OrderFirst,
            CASE WHEN cteg.dair = 1 THEN IsInvoiceAddress ELSE IsDeliveryAddress END AS OrderSecond
    FROM OrganisationAddresses
    CROSS JOIN cteg
)

SELECT OrganisationID, AddressID,
        ROW_NUMBER() OVER(PARTITION BY OrganisationID
                            ORDER BY OrderFirst DESC, OrderSecond DESC) AS [Row]
FROM cte
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...