Как я могу избежать использования T SQL SELECT в этой ситуации? - PullRequest
0 голосов
/ 09 июля 2020

Я настраиваю запрос, в котором выполняется выборка для миллионов записей. Я немного неопытен с планом выполнения, но я понимаю, что мы хотим избежать его использования из-за дополнительных накладных расходов, необходимых для отсеивания повторяющихся записей.

Есть ли способ переписать приведенное ниже Пример без использования отдельного?

IF OBJECT_ID('TEMPDB..#ORDERS', 'U') IS NOT NULL
    DROP TABLE #ORDERS

IF OBJECT_ID('TEMPDB..#CUSTOMERS', 'U') IS NOT NULL
    DROP TABLE #CUSTOMERS

CREATE TABLE #ORDERS (OrderLineItemID INT IDENTITY(1, 1), OrderID INT, PRIMARY KEY (OrderLineItemID));

CREATE TABLE #CUSTOMERS (CustomerID INT, OrderLineItemID INT, PRIMARY KEY (OrderLineItemID));

INSERT INTO #ORDERS (OrderID)
VALUES (1), (1), (1), (2), (2), (2), (2), (3), (3), (3), (3), (3), (3), (3), (5), (5), (5), (5), (5), (5);

INSERT INTO #CUSTOMERS (OrderLineItemID, CustomerID)
SELECT OrderLineItemID, CASE 
        WHEN OrderLineItemID <= 3
            THEN 15
        ELSE 20
        END
FROM #ORDERS

Результат запроса должен получить CustomerID и OrderID, но в каждом заказе есть отдельная позиция внутри. Ниже приведены все результаты.

SELECT C.CustomerID, O.OrderID
FROM #CUSTOMERS C
JOIN #ORDERS O ON C.OrderLineItemID = O.OrderLineItemID

Неразличимый результат:

CustomerID  OrderID
15  1
15  1
15  1
20  2
20  2
20  2
20  2
20  3
20  3
20  3
20  3
20  3
20  3
20  3
20  5
20  5
20  5
20  5
20  5
20  5

Но если мы добавим различие к выделенному, мы получим желаемые результаты.

SELECT DISTINCT C.CustomerID, O.OrderID
FROM #CUSTOMERS C
JOIN #ORDERS O ON C.OrderLineItemID = O.OrderLineItemID

Отчетливый результат:

CustomerID  OrderID
15  1
20  2
20  3
20  5

Есть ли лучший способ записать это, чтобы работать более эффективно?

1 Ответ

1 голос
/ 09 июля 2020

Вы можете использовать оконную функцию ROW_NUMBER() для достижения того же результата. Не уверен, даст ли это лучшую производительность. Если сомневаетесь, лучше проверьте это.

SELECT CustomerID, OrderID
FROM
(
SELECT C.CustomerID, O.OrderID, ROW_NUMBER() OVER(PARTITION BY C.CustomerID, O.OrderID ORDER BY (SELECT 1)) AS RNK
FROM #CUSTOMERS C
JOIN #ORDERS O ON C.OrderLineItemID = O.OrderLineItemID) as t
WHERE rnk = 1
...