Проблемы с написанием рекурсивного запроса - PullRequest
0 голосов
/ 15 января 2020

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

Я работаю в Teradata, используя две таблицы, которые выглядят следующим образом

Table Name             Fields
Sales                (ID, Sales)
Discounts       (ID, PromoNum, Discount)

Поле PromoNum состоит из 9 ди git уникальных промо-номеров, соответствующих купонам. Это помогает отследить, когда транзакция включает указанный купон c, который использовался. К каждой транзакции может применяться более 1 купона.

Я пытаюсь создать рекурсивный запрос, который выводит продажи и скидки для заданного набора купонов итеративным способом. Причина, по которой я делаю это итеративно, заключается в том, что к одной транзакции может быть применено более 1 купона (для 1 или более элементов). Если бы я избегал рекурсивного маршрута запроса и выполнял, например, внутреннее объединение на ID, я мог бы излишне дублировать записи, если в одной транзакции использовались два или более рекламных номера, что приводило к потенциально большим продажам или скидкам, чем актуальный. Кроме того, у меня есть доступ только для чтения к базе данных.

Я создал временную таблицу с именем Promos с 3 указанными c рекламными акциями, которые я хочу запустить интерактивно, и имеет поля PromoNum и PromoIndex. PromoIndex - это, по сути, номер строки для каждой рекламной акции, которую я пытаюсь использовать в интерактивном порядке ниже.

Рекурсивный запрос, который я написал до сих пор, приведен ниже. Это не работает, как ожидалось, из-за логики, которую я прокомментировал. Мне нужно переписать эту часть, чтобы убедиться, что она просто запускается для номера продвижения, соответствующего индексу на этой указанной итерации c. Например, когда он находится на итерации 2, он будет технически включаться в PromoIndex 1 и PromoIndex 2, когда он должен работать только для PromoIndex 2, если это имеет смысл. Я пытался переписать его, оставаясь в пределах допустимого в рекурсивном запросе, и не могу понять это.

WITH RECURSIVE PromoData AS
(
SELECT 
  1 AS PromoIndex
  , 1 AS PromoNum --dummy column
  , 0 AS Sales --dummy column
  , 0 AS Discounts --dummy column
FROM 
Dummy Table

UNION ALL

SELECT 
  PromoData.PromoIndex + 1
  , PromoData.PromoNum
  , Sales.Sales
  , Discounts.Discounts --Edited here
FROM Sales
INNER JOIN Discounts on Sales.ID = Discounts.ID
INNER JOIN Promos on Promos.PromoNum = Discounts.PromoNum and Promos.PromoIndex = PromoData.PromoIndex --Problematic portion here
WHERE PromoData.PromoIndex <= 3
)
SELECT *
FROM PromoData

Ответы [ 2 ]

0 голосов
/ 15 января 2020

Рекурсивные запросы обычно используются для разрешения нескольких слоев иерархических строк, например, с отношениями родитель / потомок. Я не думаю, что это необходимо в этом случае.

Основная проблема, которую я вижу здесь, заключается в том, что вы пытаетесь связать продажи и скидки, но я не вижу естественного способа сделать это. Например, если транзакция имеет продажи в размере 100 долларов США и две скидки в размере 10 и 20 долларов США, то какая из этих 100 долларов будет отнесена на каждую скидку? Я думаю, это то, что вы подразумевали под «двумя или более промо-номерами, которые используются в одной транзакции», вызывая раздутые цифры.

Если ваше поле ID используется как transaction_ID, вы можете попробовать что-то вроде :

WITH coupons AS (
  SELECT 'PromoID1' AS PromoNum UNION ALL
  SELECT 'PromoID2' AS PromoNum UNION ALL
  SELECT 'PromoID3' AS PromoNum
)
SELECT 
  c.PromoNum, 
  COALESCE(info.sales, 0) sales, 
  COALESCE(info.discounts, 0) discounts
FROM coupons c -- get all specified coupons
LEFT JOIN (
  SELECT 
    MAX(s.sales) sales,
    SUM(d.discount) discounts, -- Get total discount for txn
    MAX(d.PromoNum) AS PromoNum -- Pick a single PromoNum
  FROM sales s -- Get all sales
  LEFT JOIN discounts d ON s.ID = d.ID -- Get any discounts applied to sales
  GROUP BY s.ID -- One row per txn (avoid double counting sales)
) info ON c.PromoNum = info.PromoNum -- Get related sales / discounts per PromoNum

Разница в том, что в случае транзакции с несколькими скидками все продажи по этой транзакции будут связаны только с одним PromoNum. Таким образом, вы не получите завышенные цифры продаж.

Не уверен, что это то, что вам нужно, но надеюсь, что это поможет.

0 голосов
/ 15 января 2020

Из того, что вы описываете, вы хотите:

select s.*
from sales s
where exists (select 1
              from discounts d join
                   promos p
                   on d.promonum = p.promonum
              where d.id = s.id 
             );

Я не понимаю, какое отношение рекурсивный запрос имеет к описанной вами проблеме.

...