【问题标题】:How to replace a UNION in a query for a view?如何在视图查询中替换 UNION?
【发布时间】:2013-12-24 08:28:48
【问题描述】:

我创建了以下查询以在视图中使用

SELECT 
          *
      FROM
          customers c
      JOIN
          customer_business cb
      ON
          c.customer_id = cb.customer_id
union
SELECT 
          *
      FROM
          customers c
      LEFT JOIN
          customer_business
      ON
          business_id=NULL;

这使他的工作完美无缺。它显示所有与该业务相关的客户,并在最后显示所有客户与该业务的信息为空。

customer_id    |    business_id
--------------------------------
      1        |        1
      2        |        1
      2        |        2
      1        |       NULL
      2        |       NULL
      3        |       NULL

但是UNION使视图的性能很差的问题。

我尝试使用 LEFT JOIN 来实现,但没有显示所有业务为 null 的客户,只显示没有任何关联业务的客户

我知道加快查看速度的解决方案是删除那个 UNION,但我不知道怎么做。

谁能帮帮我?

谢谢

编辑

这是一个例子

Customer Table
  customer_id  |      name
--------------------------------
      1        |      test1
      2        |      test2
      3        |      test3


Customer_business Table
  customer_business_id   |   customer_id   |   business_id
----------------------------------------------------------
      1                  |        1        |        1
      2                  |        1        |        2
      3                  |        1        |        3
      4                  |        2        |        1
      5                  |        2        |        2

Expected query result:
  name    |   customer_id   |   business_id
----------------------------------------------------------
  test1   |        1        |        1
  test1   |        1        |        2
  test1   |        1        |        3
  test2   |        2        |        1
  test2   |        2        |        2
  test1   |        1        |      NULL
  test2   |        2        |      NULL
  test3   |        3        |      NULL

【问题讨论】:

  • 我不明白查询的第二部分,idbusiness=NULL 条件是什么?它似乎加入了比你想要的更多的行。您是否试图让所有客户都没有对应的 customer_business 行?
  • 提高性能的第 1 步是将 select * 替换为仅选择您需要的字段。
  • 第 2 步是了解您自己的查询以及 null 和左连接的工作原理。
  • SQL 中的 UNION 运算符消除了结果中的重复项;为此,它必须对中间结果集进行排序。如果您希望保留重复项并避免排序,请改用 UNION ALL 运算符。
  • 谢谢,我现在明白了我所做的大部分错误。

标签: mysql sql database optimization union


【解决方案1】:

根据下面的 cmets 和您想要的输出更新它。

请注意,我使用的 UNION ALLUNION 快,因为 UNION 使用 DISTINCT 来获取在您的情况下不适用的唯一记录。另外,确保customer_idCustomer 表中的PK,并尝试在Customer_Business 表中的customer_id 上添加非唯一索引,它应该有助于提高性能。

SELECT name,
    C.customer_id,
    business_id
FROM Customer C
INNER JOIN Customer_Business CB
    ON C.customer_id = CB.customer_id
UNION ALL
SELECT name,
    C.customer_id,
    NULL
FROM Customer C

【讨论】:

  • 查询的第二部分添加所有业务信息为空的客户。不仅仅是那些没有 customer_business 的人
  • 你试过我上面给出的查询了吗?您能否举例说明您在 customers 和 customer_business 表中的值以及您想要的输出?
  • 我根据您想要的输出更新了答案中的查询。立即尝试。
【解决方案2】:

排除我们知道的不高效的联合,另一个减慢查询速度的是第二个查询中的语句 ON idbusiness = NULL。

我建议像这样编辑您的查询,并将性能视为一个视图:

SELECT c.customer_id, idbusiness
FROM customers c
JOIN customer_business cb ON c.customer_id = cb.customer_id
UNION 
SELECT customer_id, NULL 
FROM customers c

编辑:

寻找替代方案你可以试试这个,它应该返回相同的输出(我已经用 0 更改了空值)但我不认为它更快:

SELECT c.customer_id, idbusiness
FROM customers c
INNER JOIN (

SELECT customer_id, idbusiness
FROM customer_business
UNION 
SELECT 0 , 0
)b ON ( c.customer_id = b.customer_id ) 
OR (
b.idbusiness =0
)

最终您可以尝试仅将子查询 b 放入视图中,或者通过将值 0,0 作为记录放入表 customer_business 中来删除联合。

【讨论】:

  • 你是对的,它有性能提升,但还是太慢了。有什么办法可以去掉工会?
  • 我认为没有办法删除联合,因为据我了解,您的查询结果必须包含同一张表的两个不同子集:一个包含客户及其业务的子集和所有客户的一个。我用替代方法编辑了答案,但我认为它不会更快。
猜你喜欢
  • 2019-04-16
  • 2012-02-20
  • 2021-08-21
  • 1970-01-01
  • 2010-09-14
  • 2012-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多