【问题标题】:Subselect and group by子选择和分组依据
【发布时间】:2012-12-25 16:29:47
【问题描述】:

我有两张桌子:

main : id_main, field1, filter

main_logs(5000 万行):auto inc、id_main、路径

我正在寻找以下结果: id_main, field1, 最常用的路径

我尝试了以下查询:

select id_main, 
  field1, 
  (select path, count(*) as cpt 
   from main_log 
   where main_log.id_main=main.id_main group by path order by cpt desc limit 1) 
from main 
where filter in (1,3,5);

Mysql 返回:操作数应包含 1 列

如果我删除路径,结果是正确的,但我错过了路径值。

select id_main, 
  field1, 
  (select path, count(*) as cpt 
   from main_log 
   where main_log.id_main=main.id_main group by path order by cpt desc limit 1) 
from main 
where filter in (1,3,5);

我不需要 count(*) 的结果,但我需要它用于“order by”

如何编写此查询以获得我的结果? 谢谢

主要

id_main     | field1    | filter
1       | red       | 1
2       | blue      | 3
3       | pink      | 1

ma​​in_logs

autoinc     | id_main   | path
1       | 1         | home1
2       | 1         | home2
3       | 1         | home2
4       | 2         | house2
5       | 2         | house7
6       | 2         | house7
7       | 3         | casee

预期结果

id_main     | fields1   | most common path
1       | red       | home2
2       | blue      | house7
3       | pink      | casee

【问题讨论】:

  • 你能显示你需要的结果吗?
  • 我需要 "main" 表中的每一行,包括 "main_log" 表中 id_main 的最常见路径
  • 我认为stackoverflow.com/questions/12446368/… 中的答案提供了构建子查询的方法。然后您可以将其与main 表连接起来。
  • 您正在尝试的查询是一个依赖查询,这将比我的和@Saharsh Shah 花费更多的时间,这是完美的
  • @benfromaix 在main 表中没有filter 数据了

标签: mysql subquery


【解决方案1】:

你需要使用:

SELECT id_main, field, 
    (SELECT path 
    FROM main_logs 
    WHERE id_main=main.id_main 
    GROUP BY path 
    ORDER BY count(path) DESC 
    LIMIT 1) AS most 
FROM main 
WHERE filter IN (1,3,5);

经过测试,可以正常工作。

【讨论】:

    【解决方案2】:

    试试这个:

    SELECT m.id_main, m.field1, A.path 
    FROM main m 
    INNER JOIN (SELECT * 
                FROM (SELECT id_main, path, COUNT(*) cnt
                      FROM main_log ml  
                      WHERE EXISTS (SELECT * FROM main m WHERE ml.id_main = m.id_main AND filter IN (1,3,5))
                      GROUP BY id_main, path 
                      ORDER BY cnt DESC
                      ) AS A 
                GROUP BY id_main
                ) AS A ON m.id_main = A.id_main;
    

    旧代码忽略

    SELECT m.id_main, m.field1, A.path 
    FROM main m 
    INNER JOIN (SELECT * FROM (SELECT id_main, path, count(*) cnt
                FROM main_log 
                GROUP BY id_main, path 
                ORDER BY cnt DESC) GROUP BY id_main) as A on m.id_main = A.id_main 
    WHERE filter IN (1,3,5);
    

    【讨论】:

    • 我认为它可以在小数据集上工作,但在我的情况下 mysql 疯了(错误 126(HY000):表 '/tmp/#sql_11dc_1.MYI' 的密钥文件不正确;尝试修复它) 因为 main_log 表很大(5Go)。此查询需要对所有表执行 subselect group by,不带任何条件。我做不到
    • 两个表中的id_main 都有索引吗?
    • 它是“main”表中的主键,它是“main_log”中的索引
    • 在路径列上添加索引并尝试运行查询
    • 其实路径上也有一个。但是没有任何 where 条件的按路径分组需要一个巨大的临时表大小。这就是为什么我试图为每个 id_main 获取最常见的路径而不是一个巨大的查询
    【解决方案3】:
    SELECT 
        m.id_main,
        m.field1,
        ml.path,
        IFNULL(ml.Count,0)
    FROM main as m
    LEFT JOIN (
               SELECT
                     id_main, 
                     path,
                     COUNT(path) as Count
               FROM main_logs
               GROUP BY id_main
              ) as ml on ml.id_main = m.id_main
    

    【讨论】:

    • 这里的答案相同:我认为它可以在小型数据集上运行,但在我的情况下 mysql 发疯了(错误 126 (HY000): Incorrect key file for table '/tmp/#sql_11dc_1.MYI';尝试修复它)因为 main_log 表很大(5Go)。此查询需要对所有表执行 subselect group by,不带任何条件。我做不到
    【解决方案4】:

    您在子查询中返回两列。您只需退回一个。

    样本数据:

    ID_MAIN     FIELD1  FILTER
    1   h   1
    2   x   2
    3   y   3
    
    
    AUTOINC     ID_MAIN     PATH
    11  1   abc
    12  2   abd
    13  1   xyz
    14  1   ghf
    15  2   xyz
    

    试试看:SQLFIDDLE

    查询:

    select id_main, 
      field1, 
      (select count(id_main) as cpt 
       from main_logs 
       where main_logs.id_main=main.id_main 
       group by path 
       order by cpt desc limit 1) as CPTs
    from main 
    where filter in (1,3,5);
    

    结果:

    ID_MAIN     FIELD1  CPTs
    1       h   1
    3       y   (null)
    

    编辑以提供每个 ID 每个路径的最大计数

    绝对不是最优雅的查询。连接和子查询也可能导致相当荒谬的性能滞后。

    遵循您的示例数据,除了表 main,id = 3,粉红色过滤器 = 5。因此它符合您的 filter 标准。但是,即使没有该条件,以下查询似乎也适用于逻辑。

    查询:

    select a.id, b.path, a.mx
    from
    (select x.id, x.path, max(x.ct) as mx
    from (
    select m.id_main as id, ml.path, 
    count(ml.id_main) as ct
    from main m
    left join 
    main_logs ml
    on ml.id_main = m.id_main
    group by ml.path) as x
    group by x.id) as a
    inner join 
    (select m.id_main as id, m.filter, ml.path, 
    count(ml.id_main) as ct
    from main m
    left join 
    main_logs ml
    on ml.id_main = m.id_main
    group by ml.path) as b
    on a.id = b.id
    and a.mx = b.ct
    where b.filter in (1,2,3)
    order by a.mx desc
    ;
    

    结果:

    ID  PATH    MX
    1   home2   2
    2   house7  2
    3   casee   1
    

    【讨论】:

    • 谢谢。但我需要我的 sql 结果中最常见的路径,而不是出现次数
    • @benfromaix 示例数据和您的预期输出 wuold 很有帮助;)
    • @benfromaix 我用性能非常难看的查询更新了答案。请试一试:)
    • 不幸的是Mysql仍然无法播放这个查询,因为它太大了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-09-28
    • 1970-01-01
    • 2021-07-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多