【问题标题】:MySQL using AliasesMySQL 使用别名
【发布时间】:2012-12-27 22:17:02
【问题描述】:

我有以下语法不正确的查询,别名为 in_Degree 和 out_degree:

insert into userData
select user_name, 
      (select COUNT(*) from tweets where rt_user_name = u.USER_NAME)in_degree,
      (select COUNT(*) from tweets where source_user_name = u.user_name)out_degree, 
      in_degree + out_degree(freq)
   from users u

查询中的问题是选择列表中的第 4 项别名为 freq。我希望第 4 项的值为 in_degree + out_degree。蛮力极慢的解决方案是复制并过去两个子查询并添加它们。

  1. 我怎样才能做到这一点又快又简单,就像 in_degree + out_degree 一样?

【问题讨论】:

    标签: mysql subquery alias


    【解决方案1】:

    您可以使用子查询:

     insert into userData
     select user_name,
       in_degree,
       out_degree,
       in_degree + out_degree
     from
     (
       select user_name, 
        (select COUNT(*) from tweets where rt_user_name = u.USER_NAME)in_degree,
        (select COUNT(*) from tweets where source_user_name = u.user_name)out_degree
       from users u
     ) src
    

    或者你可以使用:

    insert into userData
    select user_name,
      count(distinct in_t.*) in_degree,
      count(distinct out_t.*) out_degree,
      count(distinct in_t.*) + count(distinct out_t.*)
    from users u
    left join tweets in_t
      on u.USER_NAME = in_t.rt_user_name
    left join tweets out_t
      on u.USER_NAME = out_t.source_user_name
     group by u.user_name
    

    【讨论】:

    • 第二个查询需要GROUP BY u.USER_NAME 才能工作,并且计数中需要DISTINCT 以避免笛卡尔积产生的多个计数。
    • 我很喜欢子查询方法
    • @CodeKingPlusPlus:注意那些相关的子查询,他们可以用大集合吃你的午餐(性能方面)。很多时候,加入内联视图会提供更好的性能。在小型设备上,很难看到任何性能差异。当行数变得巨大时,性能差异就会被放大。
    【解决方案2】:

    正如您所发现的,除了在 HAVING 子句或 ORDER BY 子句中之外,您不能引用该选择列表中给出的别名。

    一种选择是将您的查询用作“内联视图”,并围绕它编写一个包装查询。

    • 从查询的选择列表中删除第 4 个(无效)表达式,
    • 将您的查询包装在一组括号中
    • 在结束括号后面加上别名(例如)s
    • 围绕它编写一个查询,像引用表格一样引用内联视图
    • 外部查询上的选择列表可以引用内联视图中定义的“别名”。

    但是,如果您想让这个“快速”,您可能会考虑(作为一种选择)采取完全不同的策略。您可以获取所有用户的计数,而不是使用相关子查询来获取每个用户的计数,然后使用 LEFT JOIN 运算符,例如

    SELECT u.user_name
         , IFNULL(i.cnt,0) AS in_degree
         , IFNULL(o.cnt,0) AS out_degree
         , IFNULL(i.cnt,0)+IFNULL(o.cnt,0) AS freq
      FROM users u
      LEFT
      JOIN (SELECT rt_user_name, COUNT(*) AS cnt FROM tweets 
            GROUP BY rt_user_name) i
        ON i.rt_user_name = u.user_name
      LEFT
      JOIN (SELECT source_user_name, COUNT(*) AS cnt FROM tweets 
            GROUP BY source_user_name) o
        ON o.source_user_name = u.user_name
    

    【讨论】:

    • @Sir Rufo:索引为ON tweets(rt_user_name)ON tweets(source_user_name)ON users(user_name),这可能确实是最有效的方法。这些相关的子查询可以为users 表中的大量行吃掉你的午餐(性能方面)。如果查询只查看用户表中的少量行,那么相关子查询可能会更快。
    • 我应该加粗“在这种情况下”-> 所有用户。谈论索引还应该包括使用用户 ID(INT/BIGINT)而不是用户名(字符)来提高性能并减少内存消耗:o)
    • 你又说对了,先生,Rufo 爵士。
    【解决方案3】:

    这应该可行:

    insert into userData
      SELECT T.user_name,
           T.in_degree,
           T.out_degree,
           (T.in_degree + T.out_degree) as freq
       FROM (SELECT user_name, 
              (select COUNT(*) from tweets where rt_user_name = u.USER_NAME) as in_degree,
              (select COUNT(*) from tweets where source_user_name = u.user_name) as out_degree      
               FROM users u) T
    

    【讨论】:

      【解决方案4】:

      很快,我会做这样的事情:

      insert into userData
      select 
          TMP.user_name,
          TMP.in_degree,
          TMP.out_degree,
          (TMP.in_degree + TMP.out_degree) degreeSum
      from(
          select user_name, 
              (select COUNT(*) from tweets where rt_user_name = u.USER_NAME)in_degree,
              (select COUNT(*) from tweets where source_user_name = u.user_name)out_degree
          from users u
      ) TMP
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-10-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-02-18
        • 1970-01-01
        相关资源
        最近更新 更多