Преобразование запроса ПОЛНОГО ВНЕШНЕГО СОЕДИНЕНИЯ из трех таблиц в MySQL

#mysql #sql #sql-server

#mysql #sql #sql-сервер

Вопрос:

Мне нужно перевести этот запрос, который работает на SQL Server, в MySQL. Я обошел его не менее 50 раз, и я в тупике и даже не могу найти отправную точку.

Проблемы в двух словах:

  • Он имеет не одно, а два FULL OUTER объединения, которые MySQL не выполняет. Я знаю, что это можно как-то эмулировать, используя UNION в сочетании с LEFT и RIGHT joins .
  • Он объединяет таблицы на нескольких условиях, и я не уверен, как добавить критерии исключения в ON if, выполняя типичный RIGHT JOIN
 SELECT COALESCE(ca.reporting_period, s_p.reporting_period, s_uy.reporting_period) AS reporting_period,
       COALESCE(ca.state, s_p.state, s_uy.state) AS state,
       COALESCE(ca.servicer, s_p.servicer, s_uy.servicer) AS servicer,
       COALESCE(ca.product, s_p.product, s_uy.product) AS product,
       COALESCE(ca.product_group, s_p.product_group, s_uy.product_group) AS product_group,
       COALESCE(ca.portfolio, s_p.portfolio, s_uy.portfolio) AS portfolio,
       COALESCE(ca.channel, s_p.channel, s_uy.channel) AS channel,
       ca.Gross,
       ca.Costs,
       ca.commission,
       ca.commissionable,
       s_p.WAVG_placed_numerator,
       s_p.place_balance AS WAVG_placed_denominator,
       SUM(s_uy.cum_gross) AS gross_uy_num,
       SUM(s_uy.cum_netnet) AS netnet_uy_num,
       SUM(s_uy.cum_commission) AS servicer_uy_num,
       SUM(s_uy.num_accounts) AS uy_den,
       ca.costs_recovered
# INTO adhoc_work.RevenueReport_Legal
FROM   adhoc_work.Cash ca
FULL OUTER JOIN adhoc_work.Summary_placed s_p
 ON  ca.reporting_period = s_p.reporting_period
  AND ca.state = s_p.state
  AND ca.servicer = s_p.servicer
  AND ca.product = s_p.product
  AND ca.product_group = s_p.product_group
  AND ca.portfolio = s_p.portfolio
  AND ca.channel = s_p.channel
FULL OUTER JOIN adhoc_work.Summary_uy s_uy
 ON  ca.reporting_period = s_uy.reporting_period
  AND ca.state = s_uy.state
  AND s_p.state = s_uy.state
  AND ca.servicer = s_uy.servicer
  AND s_p.servicer = s_uy.servicer
  AND ca.product = s_uy.product
  AND s_p.product = s_uy.product
  AND ca.product_group = s_uy.product_group
  AND s_p.product_group = s_uy.product_group
  AND ca.portfolio = s_uy.portfolio
  AND s_p.portfolio = s_uy.portfolio
  AND ca.channel = s_uy.channel
  AND s_p.channel = s_uy.channel
WHERE  COALESCE(ca.reporting_period,s_p.reporting_period,s_uy.reporting_period) BETWEEN DATE_FORMAT(TIMESTAMPADD(MONTH,-13,NOW(3)),'%Y%m%d') AND DATE_FORMAT(NOW(3),'%Y%m%d')
GROUP BY COALESCE(ca.reporting_period,s_p.reporting_period,s_uy.reporting_period)
   ,COALESCE(ca.state,s_p.state,s_uy.state)
   ,COALESCE(ca.servicer,s_p.servicer,s_uy.servicer)
   ,COALESCE(ca.product,s_p.product,s_uy.product)
   ,COALESCE(ca.product_group,s_p.product_group,s_uy.product_group)
   ,COALESCE(ca.portfolio,s_p.portfolio,s_uy.portfolio)
   ,COALESCE(ca.channel,s_p.channel,s_uy.channel)
   ,ca.gross
   ,ca.Costs
   ,ca.commission
   ,ca.commissionable
   ,s_p.WAVG_placed_numerator
   ,s_p.place_balance
   ,ca.costs_recovered;
  

Ответ №1:

На самом деле, ваш запрос не совсем выполняет полное внешнее соединение, потому что условие, подобное этому:

 ca.state = s_uy.state
  

требуется ca.state сопоставление. То есть внешнее соединение превращается во внутреннее соединение.

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

 FROM (SELECT reporting_period, . . .
      FROM adhoc_work.Cash ca
      UNION   -- on purpose to remove duplicates
      SELECT reporting_period, . . .
      FROM adhoc_work.Summary_placed
      UNION   -- on purpose to remove duplicates
      SELECT reporting_period, . . .
      FROM adhoc_work.Summary_uy
     ) x LEFT JOIN
     adhoc_work.Cash ca
     ON x.reporting_period = ca.reporting_period AND
        . . . LEFT JOIN
     adhoc_work.Summary_placed s_p
     ON x.reporting_period = s_p.reporting_period AND
        . . . LEFT JOIN
     adhoc_work.Summary_uy s_uy
     ON x.reporting_period = s_uy.reporting_period AND
        . . .
  

Комментарии:

1. Я пытался пойти по предложенному вами пути. Одно из препятствий заключается в том, что предлагаемые UNION вами правила требуют, чтобы все поля в UNION разделах были идентичными. Как вы можете видеть в исходном запросе, первые пять или около того полей одинаковы, но после этого они расходятся. И 1 к вашему замечанию , что исходный запрос на самом деле не является a FULL OUTER JOIN . Я начал экспериментировать с тем, чтобы просто сделать их LEFT JOIN s, и я получаю правильный, но другой ответ, в котором мой MySQL является почти полным подмножеством ответа SQL Server. Вот где я сейчас нахожусь. Я в этом над головой.