【问题标题】:How to fetch data by a conditional query(left join/right join/inner join/ multi select, ... or) from multi table如何通过条件查询(左连接/右连接/内连接/多选,...或)从多表中获取数据
【发布时间】:2018-04-02 12:04:10
【问题描述】:

我遇到了条件查询问题,无法解决,我需要您的帮助。 我将 mysql 与 innodb 一起使用,并且我有一些如下表。

表1: ---------------------- uers_type_1 ----------------------

user_id int(11) primary auto_increment
firstname varchar(15)
lastname varchar(20)
.
.
.

表 2: ---------------------- uers_type_2 ----------

user_id int(11) primary auto_increment
firstname varchar(15)
lastname varchar(20)
.
.
.

表 3: ---------------------- user_request ----------------------

request_id int(11) primary auto_increment
user_type enum("ut1","ut2")
user_id int(11)
request text

现在我需要一个查询来获取如下内容: 用户从用户类型表中请求包含用户名和姓的数据

结果:

-----------------------------------------------
- firstName - lastName - request_id - request -
-----------------------------------------------
- Robert    - De Niro  - 10         - some request.
- Will      - Smith    - 93         - some request.
.
.
.

我的查询是这样的,但它不起作用

SELECT r.request_id , r.request, (
 execute(
  concat('select u.first_name AS firstName, u.lastname AS lastName from ', 
           (SELECT CASE r.user_type WHEN 'ut1' 
           THEN 'uers_type_1' WHEN 'ut2' THEN 'uers_type_2' END), 
           ' u WHERE u.user_id = ', r.user_id, ''
  )
 )
)
FROM `user_request` r
WHERE 1

【问题讨论】:

    标签: mysql if-statement conditional


    【解决方案1】:

    我已经为你的问题找到了解决方案,

    select user_request.r_id , user_request.request,
    (select Case user_request.user_type when 'u1' then user_type_1.fistname else user_type_2.firstname end ) as name
    from user_request 
    left JOIN user_type_1 on user_request.user_id = user_type_1.id and user_request.user_type = 'u1' 
    left JOIN user_type_2 on user_request.user_id = user_type_2.id and user_request.user_type = 'u2' 
    

    重点是: 尝试使用左连接在查询中指向两个表,然后在您的选择选项中选择它应该用于获取数据的位置。

    (select Case user_request.user_type when 'u1' then user_type_1.firstname else user_type_2.firstname end ) as name,
    (select Case user_request.user_type when 'u1' then user_type_1.lastname else user_type_2.lastname end ) as family
    

    希望对你有所帮助。

    【讨论】:

    • 谢谢你亲爱的 Sir1。你的解决方案很好,我用过。但在您的解决方案中是一个大问题。我的主表有很多数据,你的解决方案有点慢。特别是在第一次执行。我只测试了 4 行,它需要 1.8365 秒,下一次执行需要 0.4231 秒相同的行。您还有其他解决方案吗?
    • 使用解释计划并查看是否正在使用索引。您可能需要针对性能调整提出一个新问题。在这样的问题中,知道存在哪些索引是必不可少的,查询和解释计划也是如此。使用文本而不是该信息的图像。
    • @Used_By_Already 是的,这是一种性能问题,应该单独考虑,谢谢您的注意
    【解决方案2】:

    拥有 2 个用户表会让您感到困惑和沮丧。虽然我不知道你为什么拥有它们,但如果可能的话,可以考虑将它们移到一张桌子上。在任何情况下,您都可以使用UNION ALL 查询生成用户信息的单一视图,如下所示:

      SELECT
            'ut1' AS user_type
          , user_id
          , firstname
          , lastname
      FROM user_type_1
      UNION ALL
      SELECT
            'ut2' AS user_type
          , user_id
          , firstname
          , lastname
      FROM user_type_2
      ;
    

    该查询实际上可能用于创建view,但它是可选的。 UNION ALL 方法可以在如下查询中用作derived table 子查询。请注意这如何简化对名称列的访问。

      SELECT
            user_request.r_id
          , user_request.request
          , u.firstname                ## simple to access
          , u.lastname                 ## simple to access
      FROM user_request AS ur
      INNER JOIN (
            SELECT
                  'ut1' AS user_type
                , user_id
                , firstname
                , lastname
            FROM user_type_1
            UNION ALL
            SELECT
                  'ut2' AS user_type
                , user_id
                , firstname
                , lastname
            FROM user_type_2
      ) AS u ON ur.user_type = u.user_type
            AND ur.user_id = u.user_id
      ;
    

    另一种选择是使用 2 个左连接,一个用于每个用户表,并将 user_type 作为连接条件包含在每个连接中。请注意,由于左连接的工作方式,名称可以为 NULL,因此您可以通过查看 COALESCE()IFNULL() 来克服它

      SELECT
            ur.r_id
          , ur.request
          , COALESCE(ut1.fistname,ut2.firstname) firstname
          , COALESCE(ut1.lastname,ut2.lastname) lastname
      FROM user_request as ur
      LEFT JOIN user_type_1 as ut1 ON ur.user_id = ut1.id
            AND ur.user_type = 'ut1'
      LEFT JOIN user_type_2 as ut2 ON ur.user_id = ut2.id
            AND ur.user_type = 'ut2'
      ;
    

    如果您应该选择创建视图,例如

    CREATE OR REPLACE VIEW users_all_v
    AS
      SELECT
            'ut1' AS user_type
          , user_id
          , firstname
          , lastname
      FROM user_type_1
      UNION ALL
      SELECT
            'ut2' AS user_type
          , user_id
          , firstname
          , lastname
      FROM user_type_2
      ;
    

    然后后续查询变得更容易组装,例如

      SELECT
            user_request.r_id
          , user_request.request
          , u.firstname                ## simple to access
          , u.lastname                 ## simple to access
      FROM user_request AS ur
      INNER JOIN users_all_v AS u ON ur.user_type = u.user_type
            AND ur.user_id = u.user_id
      ;
    

    AND即使有一天您将这 2 个用户表合并为 1 个,您也可以调整该视图,并且现有查询不会被破坏。

    【讨论】:

    • 谢谢亲爱的朋友。您的解决方案很好,但在这种情况下,对于所有用户来说,从视图中使用或从一张表中使用并不是最佳的。而且我知道最好将所有用户表混合在一个表中,但在这种情况下,用户数据之间的差异太大,如果我将这些表加入一个表中,内存开销会很高,因为每个表都有很多用户并且非常不同的数据列和许多单元格应该是空的。
    • 我理解这些事情的困难。但是使用几个常见列的视图will be just as efficient 就像使用 2 个左连接。而且,您的后续查询将更易于编写。不要在视图中使用 order by,这是一个常见的错误。视图只是存储的查询。
    猜你喜欢
    • 1970-01-01
    • 2011-12-11
    • 2016-02-17
    • 2015-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-16
    相关资源
    最近更新 更多