如何使用union加入表? MySQL的

时间:2014-10-25 07:35:00

标签: mysql sql

我有两张桌子:

  1. 历史
  2. 业务
  3. 我想运行此查询:

    SELECT name, talias.*
    FROM
        (SELECT business.bussName as name history.*
            FROM history 
            INNER JOIN business on history.bussID = business.bussID
            WHERE history.activity = 'Insert' OR history.activity = 'Update' 
        UNION 
            SELECT name as Null, history.*
            FROM history 
            WHERE history.activity = 'Delete'
    
        ) as talias  
    WHERE 1 
    order by talias.date DESC
    LIMIT $fetch,20
    

    这个查询需要13秒,我认为问题是Mysql加入了历史和业务表中的所有行!虽然它应该只加入20行!

    我该怎么办呢?

2 个答案:

答案 0 :(得分:0)

试试这个:

SELECT h.*
FROM history AS h
WHERE (h.activity IN ('Insert', 'Update')
        AND EXISTS (SELECT * FROM business AS b WHERE b.bussID = h.bussID))
    OR h.activity = 'Delete'
ORDER BY h.date DESC
LIMIT $fetch, 20

要使ORDER BYLIMIT有效,请确保您在history.date上有索引。

答案 1 :(得分:0)

如果我理解正确,您希望活动为deleted的历史记录中的所有行加上活动所在的所有行'插入'或者'更新' 商家信息表中有相应的行。

我不知道这是否会比您的查询更快 - 您需要检查执行计划以验证这一点。

SELECT  *
FROM history 
where activity = 'Delete'
   or (     activity in ('Insert','Update')
        AND exists (select 1 
                    from business 
                    where history.bussID = business.bussID))
order by `date` DESC
LIMIT $fetch,20

修改(问题发生变化后)

如果确实需要业务表中的列,则将union替换为外部联接可能会提高性能。

但说实话,我并不期待它。 MySQL优化器并不是非常聪明,如果外连接实际上是使用某种联合实现的,我不会感到惊讶。再次,只有您可以通过查看执行计划来测试它。

SELECT h.*,
       b.bussName as name
FROM history 
  LEFT JOIN business b 
         ON h.bussID = b.bussID
        AND h.activity in ('Insert','Update')
WHERE h.activity in ('Delete', 'Insert','Update')
ORDER BY h.`date` DESC
LIMIT $fetch,20

顺便说一句:date是一个可怕的专栏名称。首先是因为它是一个保留字,第二个(更重要)因为它没有记录任何东西。那是"创作日期"? "删除日期"? A"截止日期"?还有其他日期吗?