【问题标题】:Subqueries and Union子查询和联合
【发布时间】:2015-07-08 05:01:49
【问题描述】:

我有下一个 mysql 表

如果不存在 `my_app`.`hotel`,则创建表( `id` INT NOT NULL AUTO_INCREMENT, `name` VARCHAR(45) NOT NULL, `destination_id` INT NOT NULL, 主键(`id`), INDEX `idx_name` (`name` ASC), 索引`fk_hotel_destination1_idx`(`destination_id` ASC), 约束`fk_hotel_destination1` 外键(`destination_id`) 参考 `my_app`.`destination` (`id`) 删除无操作 更新无动作) 引擎 = InnoDB 如果不存在 `my_app`.`hotel_alias`,则创建表( `id` INT NOT NULL AUTO_INCREMENT, `hotel_id` INT NOT NULL, `name` VARCHAR(45) NOT NULL, 主键(`id`), INDEX `idx_name` (`name` ASC), 索引 `fk_hotel_alias_hotel_idx` (`hotel_id` ASC), 约束`fk_hotel_alias_hotel` 外键(`hotel_id`) 参考 `my_app`.`hotel` (`id`) 删除无操作 更新无动作) 引擎 = InnoDB 如果不存在 `my_app`.`destination`,则创建表( `id` INT NOT NULL AUTO_INCREMENT, `name` VARCHAR(45) NOT NULL, 主键(`id`), 索引 `idx_name` (`name` ASC)) 引擎 = InnoDB 如果不存在 `my_app`.`place` 则创建表( `id` INT NOT NULL AUTO_INCREMENT, `name` VARCHAR(45) NOT NULL, `destination_id` INT NOT NULL, 主键(`id`), INDEX `idx_name` (`name` ASC), 索引`fk_place_destination1_idx`(`destination_id` ASC), 约束`fk_place_destination1` 外键(`destination_id`) 参考 `my_app`.`destination` (`id`) 删除无操作 更新无动作) 引擎 = InnoDB

我想创建一个视图来填充 jquery 自动完成功能,所以我进行了下一个查询

SELECT name, 'hotel' AS type, (SELECT id FROM destination WHERE hotel.destination_id = destination.id) AS destination_id FROM hotel 联盟 SELECT name, 'place' AS type, (SELECT id FROM destination WHERE place.destination_id = destination.id) AS destination_id FROM place 联盟 SELECT name, 'alias' AS type, (SELECT destination.id FROM destination,hotel WHERE hotel_alias.hotel_id = hotel.id AND hotel.destination_id = destination.id) AS destination_id FROM hotel_alias

返回以下结果

|名称 |类型 |destination_id -------------------------------------------------- - |酒店 casa maya |酒店 |1 |桑多斯卡拉科尔 |酒店 |2 |卡瓦尼亚斯图卢姆 |酒店 |3 |桑多斯豪华 |酒店 |1 |海洋水疗 |酒店 |1 |sandos playacar |酒店 |2 |沃尔玛 |地点 |1 |沃尔玛 |地点 |2 |中心 |地点 |3 |campo de golf pok-ta-pok |地点 |1 |sandos beach scape |别名 |2 |日落温泉 |别名 |1

结果是正确的,但我想知道我是否正确使用“子查询”和“联合”,或者是否有更好的方法通过优化查询来生成相同的结果?

感谢!

【问题讨论】:

  • 您的查询为您提供了您想要的结果,这意味着您已经很好地使用了它们 - 但是是的,您可以用另一种方式做到这一点,而无需使用相关的子查询(对外部查询)

标签: mysql database subquery union


【解决方案1】:

你可以使用 JOIN

看看:http://dev.mysql.com/doc/refman/4.1/en/join.html

【讨论】:

    【解决方案2】:

    您无需借助多个相关子查询即可获得所需的结果,方法是先执行联合,然后内部连接到目标表以确保目标存在且有效。

    select q.name, q.type, d.id  
      from (        
        select name, 'hotel' as type, destination_id as d_id
          from hotel
        union all
        select name, 'place' as type, destination_id as d_id
          from place
        union all
        select ha.name, 'alias' as type, destination_id as d_id
          from hotel_alias ha
            inner join hotel h
              on ha.hotel_id = h.id
       ) q
       inner join destination d
         on q.d_id = d.id
    

    没有依赖子查询,union all 以避免明显的清除,结果与您的查询相同。 demo here.

    由于您想将此用作视图,您可以将查询扩展为:

    select hotel.name, 'hotel' as type, destination_id as d_id
      from hotel
        inner join destination d1
          on hotel.destination_id = d1.id
    union all
    select place.name, 'place' as type, destination_id as d_id
      from place
        inner join destination d2
          on place.destination_id = d2.id
    union all
    select ha.name, 'alias' as type, destination_id as d_id
      from hotel_alias ha
        inner join hotel h
          on ha.hotel_id = h.id
        inner join destination d3
          on h.destination_id = d3.id
    

    或使用原始查询,将其拆分为两个视图

    create view v1 as 
      select name, 'hotel' as type, destination_id as d_id
        from hotel
      union all
        select name, 'place' as type, destination_id as d_id
          from place
      union all
        select ha.name, 'alias' as type, destination_id as d_id
          from hotel_alias ha
            inner join hotel h
              on ha.hotel_id = h.id
    

    然后

    create view YOUR_VIEW as
      select v1.name, v1.type, d.id
        from v1
          inner join destination d
            on v1.d_id = d.id
      order by type, name;
    

    然后

    select * from YOUR_VIEW

    会给你想要的结果。

    updated fiddle 显示所有上述选项。

    【讨论】:

    • dev.mysql.com/doc/refman/5.0/en/create-view.html SELECT 语句的 FROM 子句中不能包含子查询。
    • @MiguelAlejandroLazcano 我没有包含视图部分,因为它不包含在选择查询中,所以我认为它只是语言。修改成功作为一个视图是微不足道的。我现在就这样做
    • @MiguelAlejandroLazcano 你去。在视图形式中,带有更新的演示以检查
    【解决方案3】:

    无论您为获得结果所做的一切都是正确的。没有任何其他方法可以生成相同的结果。

    【讨论】:

    • 什么?他可以加入而不是使用子查询。所以至少有另一种方式
    • 在join的帮助下只能得到普通记录。所有表中都可用的记录不会出现。但是,他想要所有三个表中的所有记录。所以join操作是行不通的。 @pala_
    • 是的。这是通过joins + union完成的。这正是我所说的,使用连接而不是子查询。我没有说只使用连接。
    • 使用 join + union 有什么好处。为了获得好处,处理速度会很慢,您将无法获得所需的输出。甚至查询也会太长。 @pala_
    • 你不会得到你想要的输出意味着没有其他方法@pala_
    猜你喜欢
    • 1970-01-01
    • 2017-11-02
    • 2015-05-04
    • 1970-01-01
    • 2011-06-13
    • 1970-01-01
    • 2019-05-25
    • 1970-01-01
    • 2020-01-09
    相关资源
    最近更新 更多