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

2016-12-08 17:10:25 +08:00
 enenaaa

有这样一个表


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

4113 次点击
所在节点    MySQL
14 条回复
sagaxu
2016-12-08 17:34:19 +08:00
select logtime,count(*) as cnt from t group by logtime order by logtime

然后业务代码里,对 cnt 值进行迭代累加,遍历一次即可,业务代码算法复杂度 O(n)
liprais
2016-12-08 17:41:59 +08:00
不用 mysql 就行了
sgzhan
2016-12-08 17:56:16 +08:00
为什么不能
select logtime, count(id) as cnt from t where id<=logtime group by logtime 不就符合你的需求么?
enenaaa
2016-12-08 17:59:50 +08:00
@sgzhan id 和 logtime 之间没有对应联系。 而且你这个语句也不对, group by 是用 logtime 分组,不包含小于当前值的行
akira
2016-12-08 18:07:03 +08:00
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
2016-12-08 18:29:53 +08:00
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
2016-12-08 18:32:39 +08:00
@weizhiyao008 忘记看节点了, mysql 。。逃。。
iEverX
2016-12-08 18:46:12 +08:00
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
2016-12-08 19:17:47 +08:00
3 楼正解
多表统计也可以使用 3 楼的方法
非常方便
Aksura
2016-12-08 21:44:57 +08:00
5 楼才是正解, 3 楼的不符合题意。
enenaaa
2016-12-08 21:47:42 +08:00
@akira
@weizhiyao008
@iEverX
谢谢, 你们思路是对的。我想歪了
tusj
2016-12-09 10:20:10 +08:00
我在想, 如果表很大, 这种 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
2016-12-09 10:46:43 +08:00
@tusj 我的看法,排除掉索引的影响,没有本质区别。 这几种写法都是转换成了 join ,运算复杂度都是 n*n 级别。
tusj
2016-12-09 13:49:34 +08:00
@enenaaa 执行计划不一样.
你可以 explain 看一下.

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/326231

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX