【问题标题】:optimizing joins in union queries优化联合查询中的连接
【发布时间】:2012-03-14 08:17:21
【问题描述】:

如何使用联合和联接优化查询?是否可以在这里将一些联接移到联合之外?

(
    SELECT accounting.id, accounting.time, accounting.subaccount_id AS module_id, accounting.balance_invoice_id AS balance_id, accounting.currency_amount*-1 AS currency_amount, accounting.amount*-1 AS amount, enclosure.enc_id_, enclosure.txt, currency.name AS currency_name, IF(balance_invoice.amount, accounting.currency_amount*-1+SUM(balance_invoice.amount), accounting.currency_amount*-1) AS balance
    FROM accounting
    INNER JOIN enclosure ON enclosure.id=accounting.enc_id
    LEFT JOIN currency ON currency.id=accounting.currency_id
    LEFT JOIN balance_invoice ON balance_invoice.accounting_id=accounting.id
    WHERE accounting.att_booked=1
    GROUP BY accounting.id
)
UNION (
    SELECT accounting.id, accounting.time, accounting.subaccountoff_id AS module_id, accounting.balanceoff_invoice_id AS balance_id, accounting.currency_amount, accounting.amount, enclosure.enc_id_, enclosure.txt, currency.name AS currency_name, IF(balance_invoice.amountoff, accounting.currency_amount+SUM(balance_invoice.amountoff), accounting.currency_amount) AS balance
    FROM accounting
    INNER JOIN enclosure ON enclosure.id=accounting.enc_id
    LEFT JOIN currency ON currency.id=accounting.currency_id
    LEFT JOIN balance_invoice ON balance_invoice.accounting_id=accounting.id
    WHERE accounting.att_booked=1 && accounting.type IN (0,1,2)
    GROUP BY accounting.id
) ORDER BY time DESC

【问题讨论】:

  • 您的查询包含 'GROUP BY accounting.id' 子句和 SELECT 子句中的许多未聚合字段。 MySQL 允许,但不正确;检查一下,也许重写你的查询。

标签: mysql join union


【解决方案1】:

类似的东西-

SELECT
  a.id,
  a.time,
  IF(a.acc_type = 1, a.subaccount_id, subaccountoff_id) AS module_id,
  IF(a.acc_type = 1, a.balance_invoice_id, balanceoff_invoice_id) AS balance_id,
  IF(a.acc_type = 1, a.currency_amount * -1, currency_amount) AS currency_amount,
  IF(a.acc_type = 1, a.amount * -1, a.amount) AS amount,
  e.enc_id_,
  e.txt,
  c.name AS currency_name,
  IF(a.acc_type = 1,
    IF(bi.amount, a.currency_amount * - 1 + SUM(bi.amount), a.currency_amount * -1),
    IF(bi.amountoff, a.currency_amount + SUM(bi.amountoff), a.currency_amount)
  ) AS balance
FROM (
  SELECT 1 acc_type, a1.* FROM accounting a1 WHERE a1.att_booked = 1
    UNION
  SELECT 2 acc_type, a2.* FROM accounting a2 WHERE a2.att_booked=1 AND a2.type IN (0,1,2)
  ) a
INNER JOIN enclosure e
  ON e.id = a.enc_id
LEFT JOIN currency c
  ON c.id = a.currency_id
LEFT JOIN balance_invoice bi
  ON bi.accounting_id = a.id
GROUP BY
  a.id
ORDER BY
  time DESC;

【讨论】:

  • 哇,这令人印象深刻。但它更快吗?如果是这样,为什么? (这对我来说很有趣(也许我不是唯一一个;)))
  • @Olivier Pons 必须对两个查询进行分析和比较(EXPLAIN SELECT)。我认为这个查询应该更快,我在类似的例子中检查了这个。
【解决方案2】:

这也应该在没有 UNION 的情况下工作。我改用了几个 CASE 语句。未经测试:

SELECT a.id, a.time
      ,CASE WHEN a.type IN (0,1,2) THEN a.subaccountoff_id      ELSE a.subaccount_id      END AS module_id
      ,CASE WHEN a.type IN (0,1,2) THEN a.balanceoff_invoice_id ELSE a.balance_invoice_id END AS balance_id
      ,CASE WHEN a.type IN (0,1,2) THEN a.currency_amount       ELSE a.currency_amount*-1 END AS currency_amount
      ,CASE WHEN a.type IN (0,1,2) THEN a.currency_amount       ELSE a.amount*-1          END AS amount
      ,e.enc_id_, e.txt, c.name AS currency_name
      ,CASE WHEN a.type IN (0,1,2)
            THEN IF (b.amountoff, a.currency_amount + SUM(b.amountoff), a.currency_amount) 
            ELSE IF (b.amount,    a.currency_amount*-1 + SUM(b.amount), a.currency_amount*-1) END AS balance
FROM   accounting a
JOIN   enclosure e ON e.id = a.enc_id
LEFT   JOIN currency c ON c.id = a.currency_id
LEFT   JOIN balance_invoice b ON b.accounting_id = a.id
WHERE  a.att_booked = 1
GROUP  BY a.id
ORDER  BY a.time DESC

【讨论】:

    猜你喜欢
    • 2016-11-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-01
    • 2020-12-17
    • 1970-01-01
    • 1970-01-01
    • 2018-04-07
    • 2020-07-24
    相关资源
    最近更新 更多