› MySQL 5.5 Community Server
› MySQL 5.6 Community Server
› Percona Configuration Wizard
› XtraBackup 搭建主从复制
Great Sites on MySQL
› Percona
› MySQL Performance Blog
› Severalnines
推荐管理工具
› Sequel Pro
› phpMyAdmin
推荐书目
› MySQL Cookbook
MySQL 相关项目
› MariaDB
› Drizzle
参考文档
› http://mysql-python.sourceforge.net/MySQLdb.html
enenaaa
V2EX  ›  MySQL

这样的需求,一条 sql 语句没法搞定吧

  •  
  •   enenaaa · Dec 8, 2016 · 5144 views
    This topic created in 3593 days ago, the information mentioned may be changed or developed.

    有这样一个表

    
    |id|logtime|
    |----| ----|
    | 1 | 5 |
    | 2 | 6 |
    | 3 | 6 |
    | 4 | 8 |
    | 5 | 8 |
    

    现在需要按 logtime 分组查询,每行求 logtime 小于等于当前值的 id 数。 例如 logtime=8 这行,求 logtime <= 8 的 count(id) 值。 最终结果是这样:

    
    |count|logtime|
    |----|----|
    | 1 | 5 |
    | 3 | 6 |
    | 5 | 8 |
    
    

    在一条 sql 语句内完成整表查询,不能用存储过程,不能用临时表,表变量,存储函数。 按我的理解,数据库查询是每行扫描一次。这个查询里一行需要重复扫描多次,应该是没法一次搞定的。 诸位有何良策。

    14 replies  •  2016-12-09 13:49:34 +08:00
    sagaxu
        1
    sagaxu  
       Dec 8, 2016 via Android
    select logtime,count(*) as cnt from t group by logtime order by logtime

    然后业务代码里,对 cnt 值进行迭代累加,遍历一次即可,业务代码算法复杂度 O(n)
    F281M6Dh8DXpD1g2
        2
    F281M6Dh8DXpD1g2  
       Dec 8, 2016
    不用 mysql 就行了
    sgzhan
        3
    sgzhan  
       Dec 8, 2016
    为什么不能
    select logtime, count(id) as cnt from t where id<=logtime group by logtime 不就符合你的需求么?
    enenaaa
        4
    enenaaa  
    OP
       Dec 8, 2016
    @sgzhan id 和 logtime 之间没有对应联系。 而且你这个语句也不对, group by 是用 logtime 分组,不包含小于当前值的行
    akira
        5
    akira  
       Dec 8, 2016   ❤️ 1
    select count(1) `count` ,b.logtime from test ,
    (
    select distinct logtime from test
    )b
    where test.logtime <= b.logtime
    group by b.logtime
    order by b.logtime
    weizhiyao008
        6
    weizhiyao008  
       Dec 8, 2016   ❤️ 1
    mssql
    ```
    select b.logtime,(select count(id) from table1 a where a.logtime <= b.logtime) as logcount
    from table1 b
    group by b.logtime
    ```
    weizhiyao008
        7
    weizhiyao008  
       Dec 8, 2016
    @weizhiyao008 忘记看节点了, mysql 。。逃。。
    iEverX
        8
    iEverX  
       Dec 8, 2016   ❤️ 1
    SELECT
    COUNT(1) AS cnt, a.logtime
    FROM
    (SELECT DISTINCT
    logtime
    FROM
    my) a
    JOIN
    my b ON a.logtime >= b.logtime
    GROUP BY a.logtime;
    TaMud
        9
    TaMud  
       Dec 8, 2016
    3 楼正解
    多表统计也可以使用 3 楼的方法
    非常方便
    Aksura
        10
    Aksura  
       Dec 8, 2016
    5 楼才是正解, 3 楼的不符合题意。
    enenaaa
        11
    enenaaa  
    OP
       Dec 8, 2016
    @akira
    @weizhiyao008
    @iEverX
    谢谢, 你们思路是对的。我想歪了
    tusj
        12
    tusj  
       Dec 9, 2016
    我在想, 如果表很大, 这种 join 加 group by 的写法会不会很耗资源和时间?
    如果楼主手上有数据可以对比一下, 看看在 logtime 是索引的情况下, 哪种快些.

    use test;
    drop table if exists test;
    create table test (id bigint, logtime bigint);
    insert into test values (1, 5);
    insert into test values (2, 6);
    insert into test values (3, 6);
    insert into test values (4, 8);
    insert into test values (5, 8);
    commit;

    -- 楼上各位的写法
    SELECT COUNT(1) le_count, b.logtime
    FROM test,
    (
    SELECT DISTINCT logtime
    FROM test
    ) b
    WHERE test.logtime <= b.logtime
    GROUP BY b.logtime
    ORDER BY b.logtime

    -- 我的写法
    SELECT (
    SELECT COUNT(1)
    FROM test t
    WHERE t.logtime <= a.logtime) as le_count, a.logtime
    FROM (
    SELECT DISTINCT logtime
    FROM test) a;
    enenaaa
        13
    enenaaa  
    OP
       Dec 9, 2016
    @tusj 我的看法,排除掉索引的影响,没有本质区别。 这几种写法都是转换成了 join ,运算复杂度都是 n*n 级别。
    tusj
        14
    tusj  
       Dec 9, 2016
    @enenaaa 执行计划不一样.
    你可以 explain 看一下.
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   988 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 789ms · UTC 20:06 · PVG 04:06 · LAX 13:06 · JFK 16:06
    ♥ Do have faith in what you're doing.