Как оптимизировать вложенный SELECT - PullRequest
0 голосов
/ 20 марта 2019

У меня есть приведенный ниже SQL, который необходимо оптимизировать (имя «свойства» было изменено на более общее в приведенном ниже коде):

Он работает в Azure SQL

SELECT ContactValueA, ContactValueB, SUM(X.Price) as Price, SUM(X.ValueX) AS ValueX, SUM(X.ValueY) AS ValueY, Count (*) As [Count]
FROM
    (
        SELECT OL.id, O.ContactValueA, O.ContactValueB,
        OL.Price,
        OL.ValueX,
        OL.ValueY
        FROM [OrderLines] AS OL
        JOIN [Orders] AS O
        ON OL.OrderId = O.Id
        WHERE O.Id in 
            (
                SELECT MIN(SO.Id) AS OID
                FROM [Orders] AS SO
                WHERE SO.[Type] = 'cake'
                AND SO.Created >= @begin  and SO.Created < @end
                AND NOT EXISTS
                (
                    SELECT 1
                    FROM [3Orders] AS SOA
                    WHERE SOA.ExtOrderId = SO.ExtOrderId
                    AND SOA.[Type] = 'cake'
                    AND SOA.Created < @begin
                )
                GROUP BY SO.ExtOrderId
            )   
    ) X
GROUP BY X.ContactValueA, X.ContactValueB

@ begin и @end оба DateTimeOffset

Если мы посмотрим на эту часть кода:

                SELECT MIN(SO.Id) AS OID
                FROM [Orders] AS SO
                WHERE SO.[Type] = 'cake'
                AND SO.Created >= @begin  and SO.Created < @end
                AND NOT EXISTS
                (
                    SELECT 1
                    FROM [3Orders] AS SOA
                    WHERE SOA.ExtOrderId = SO.ExtOrderId
                    AND SOA.[Type] = 'cake'
                    AND SOA.Created < @begin
                )
                GROUP BY SO.ExtOrderId

О таблице заказов - Каждый заказ имеет уникальный идентификатор и неуникальный ExtOrderId - поскольку запись в таблице заказов может быть частичным заказом (частичные заказы имеют один и тот же ExtOrderId)

В приведенном выше коде мне нужно просмотреть все заказы (частичные заказы) между двумя datetimeoffsets - и взятьчастичные заказы с наименьшим идентификатором - но идентификатор частичного заказа (ExtOrderId) не должен иметь заказ до даты начала.

Есть предложения, как это оптимизировать?

Ответы [ 3 ]

0 голосов
/ 20 марта 2019

Вместо использования подзапроса я бы использовал левое соединение и возвращал строки без предыдущего порядка.

Ваш запрос:

        SELECT MIN(SO.Id) AS OID
        FROM [Orders] AS SO
        WHERE SO.[Type] = 'cake'
        AND SO.Created >= @begin  and SO.Created < @end
        AND NOT EXISTS
        (
            SELECT 1
            FROM [3Orders] AS SOA
            WHERE SOA.ExtOrderId = SO.ExtOrderId
            AND SOA.[Type] = 'cake'
            AND SOA.Created < @begin
        )
        GROUP BY SO.ExtOrderId

будет:

            SELECT MIN(SO.Id) AS OID
            FROM [Orders] AS SO
                 LEFT JOIN [3Orders] AS SOA ON     SOA.ExtOrderId = SO.ExtOrderId
                                               AND SOA.[Type] = 'cake'
                                               AND SOA.Created < @begin
            WHERE     SO.[Type] = 'cake'
                  AND SO.Created >= @begin  and SO.Created < @end
                  AND SOA.Id IS NULL -- Here we ensure that it has no previous orders
            GROUP BY SO.ExtOrderId
0 голосов
/ 20 марта 2019

Попробуйте это

WITH T AS (
    SELECT MIN(SO.Id) AS OID
    FROM [Orders] AS SO
    WHERE SO.[Type] = 'cake' AND SO.Created < @end
    GROUP BY SO.ExtOrderId 
    HAVING MIN(SO.Created) >= @begin
), T1 AS (
    SELECT OL.id, O.ContactValueA, O.ContactValueB,
        OL.Price,
        OL.ValueX,
        OL.ValueY
    FROM [OrderLines] AS OL
    INNER JOIN T ON T.OID = OL.OrderId
    INNER JOIN [Orders] AS O ON T.OID = O.Id
) SELECT ContactValueA, ContactValueB, SUM(T1.Price) as Price, SUM(T1.ValueX) AS ValueX, SUM(T1.ValueY) AS ValueY, Count (*) As [Count]
FROM T1 
GROUP BY T1.ContactValueA, T1.ContactValueB
0 голосов
/ 20 марта 2019

используйте row_number() аналитическую функцию для получения минимального идентификатора

with cte as
(

SELECT OL.id, O.ContactValueA, O.ContactValueB,
        OL.Price,
        OL.ValueX,
        OL.ValueY,
        row_number()over(partition by O.type order by o.id) rn
        FROM [OrderLines] AS OL
        JOIN [Orders] AS O
        ON OL.OrderId = O.Id
) ContactValueA, ContactValueB, SUM(Price) as Price, SUM(ValueX) AS ValueX, SUM(ValueY) AS ValueY, Count (*) As [Count] from cte where rn=1
group by ContactValueA, ContactValueB
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...