HANA SQL: как присоединиться к первой строке при условии обращения к основной таблице - PullRequest
0 голосов
/ 04 января 2019

Я буду использовать гипотетический пример, чтобы проиллюстрировать мою проблему объединения двух таблиц, на которых я застрял довольно давно:

Каждый Заказ имеет много дат и количеств поставки:

Заказать

OrderID   DeliveryID  DeliveryDate     Quantity
=======   ==========  ============     ========
1000      001         2017-01-01       10
1000      002         2017-01-08       10
1000      003         2017-01-15       10
1001      001         ....             10

Полученные товары 1013 * отображаются на OrderID, но не DeliveryID:

Полученное

OrderID   InvoiceID   ReceivedDate   ReceivedQuantity
=======   =========   ============   ================
1000      1001        2017-01-01     10 
1000      1002        2017-01-09     09
1000      1003        2017-01-10     01
1000      1004        2017-01_15     10

Я сейчас пытаюсь присоединить таблицу Received к моей таблице Order. Но поскольку, например, второй заказ получен в два отдельных этапа, я хочу присоединить заказ к последней полученной строке, поскольку только тогда мой заказ полностью поступил.

При обычном присоединении через OrderID мы получили бы, в верхнем примере 3 Заказа и 4 Получения, всего 12 соединенных элементов.

Итак, я хочу решить эту проблему, накапливая количество для каждого идентификатора заказа и каждой поставки относительно идентификатора заказа, при этом мои скорректированные таблицы выглядят так:

Заказать

OrderID   DeliveryID  DeliveryDate     Quantity   OrderedAccumQuant
=======   ==========  ============     ========   ================
1000      001         2017-01-01       10         10
1000      002         2017-01-08       10         20
1000      003         2017-01-15       10         30
1001      001         ....             10         10

Полученное

OrderID   InvoiceID   ReceivedDate   ReceivedQuantity   AccumQuant
=======   =========   ============   ================   ================
1000      1001        2017-01-01     10                 10
1000      1002        2017-01-09     09                 19
1000      1003        2017-01-10     01                 20
1000      1004        2017-01_15     10                 30

Моя запланированная логика теперь состоит в том, чтобы соединить таблицу Received с таблицей Order с первой строкой Received, которая имеет равное или большее значение ReceivedAccumQuant, чем OrderedAccumQuant. В этом примере InvoiceID 1002 не объединяется, поскольку его доставленное количество не является заказанным количеством.

Желаемый выход:

                                          Ordered                      Rec
OrderID   DelivID  DeliveryDate   Quant   AccQuant  RecDate InvoiceID  AccQu
=======   =======  ============   =====   =======   ======= =========  =====
1000      001      2017-01-01     10      10        .-01-01 1001       10
1000      002      2017-01-08     10      20        .-01-10 1003       20
1000      003      2017-01-15     10      30        .-01-15 1004       30
1001      001      ....                

Требуемый вывод будет отображать меня в каждом OrderID: совпадение всех DeliveryID с InvoiceID, где receive_accumulated_quantity> =, чем order_accumulated_quantity

Мои два подхода:

Проблема выделения памяти

Один из подходов заключался во внутреннем присоединении к таблице «Получено» через подзапрос, а затем в ранжировании () объединяемой таблицы после разделения по OrderID и DeliveryID, а также включения условия WHERE, что Delivery.Cum_Quant> = Order.Cum_Quant. С самым внешним условием WHERE CUM_RANK = 1 мы фильтруем только первую запись для DeliveryID, которая удовлетворяет условию.

Это решение хорошо работает для небольшой части моего набора данных, но происходит сбой, как только я использую полный набор данных из-за выделения памяти, так как многие полученные элементы соединяются с элементами заказа перед тем, как их фильтрует CUM_RANK из 1 Приблизительно с 5 миллионами запланированных дат поставки и 5 миллионами дат получения и до 100 поставок на OrderID объединенная таблица становится невероятно большой:

SELECT 
  *
  ,RANK() OVER(PARTITION BY Received.OrderID, Received.DeliveryID ORDER BY Received.CUM_QUANT) as CUM_RANK
FROM Orders
JOIN 
  (
  SELECT  
    *
    ,RANK() OVER(PARTITION BY Received.OrderID ORDER BY ReceivedDate) AS Rank
    ,SUM(QUANTITY) OVER(PARTITION BY Received.OrderID ORDER BY ReceivedDate) AS Cum_Quant
  FROM Received
  )
ON Orders.OrderID =  Delivery.OrderID
WHERE
  Received.Cum_Quant >= Order.Cum_Quant
ORDER BY Orders.OrderID, Received.Cum_Quant
)
WHERE CUM_RANK = 1;

Мое сообщение об ошибке следующее: SAP DBTech JDBC: [4]: ​​не удается выделить достаточно памяти: проверьте трассировку для получения дополнительной информации

Есть идеи, как к этому подойти?

Доступ к проблеме основного стола

Мое другое предположение состояло в том, чтобы сделать сравнение Received.AccumQuant и Orders.AccumQuant в подзапросе SELECT оператора JOIN, чтобы мы избегали выполнения множества объединений. Но из оператора JOIN вы не можете получить доступ к таблице Orders:

SELECT *
FROM Orders
JOIN (
  SELECT * FROM (

    SELECT
    *
    ,ROW_NUMBER() OVER(PARTITION BY OrderID ORDER BY ReceivedDate ASC) AS RowNumb
    FROM Delivery 
    WHERE 
    WHERE Orders.OrderID = Received.OrderID 
    AND Received.AccumQuant >= Orders.AccumQuant --(this point doesnt worke since we cannot access the Orders table from here)
    ) AS DeliveryRanked
  ON Orders.OrderID = Received.OrderID

1 Ответ

0 голосов
/ 04 января 2019

Вы можете попробовать это, но я не уверен, полностью ли я понял ваш запрос.

SELECT a.orderID,MAX(a.DeliveryDate) DeliveryDate,SUM(a.Quantity) Quantity,b.ReceivedDate,b.ReceivedQuantity
FROM Orders a,
(SELECT orderID,MAX(ReceivedDate) ReceivedDate, SUM(ReceivedQuantity) ReceivedQuantity 
FROM Received
GROUP BY orderID) b
WHERE a.OrderID = b.OrderID 
GROUP BY a.orderID,b.ReceivedDate,b.ReceivedQuantity
HAVING SUM(a.Quantity)<=b.ReceivedQuantity
...