sql: 按 x,y,z 分组;返回按 f(z) 最低的 x,y 分组

Posted

技术标签:

【中文标题】sql: 按 x,y,z 分组;返回按 f(z) 最低的 x,y 分组【英文标题】:sql: Group by x,y,z; return grouped by x,y with lowest f(z) 【发布时间】:2010-03-18 12:07:36 【问题描述】:

这是给http://cssfingerprint.com

我收集有关我使用的不同方法在不同浏览器等上执行速度的时间统计数据,以便优化抓取速度。另外,我有一份关于每个方法为少数具有已知正确值的 URL 的返回值的报告,以便我可以判断哪些方法在哪些浏览器上是伪造的。 (每个都不一样,唉。)

相关表如下所示:

CREATE TABLE `browser_tests` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `bogus` tinyint(1) DEFAULT NULL,
  `result` tinyint(1) DEFAULT NULL,
  `method` varchar(255) DEFAULT NULL,
  `url` varchar(255) DEFAULT NULL,
  `os` varchar(255) DEFAULT NULL,
  `browser` varchar(255) DEFAULT NULL,
  `version` varchar(255) DEFAULT NULL,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  `user_agent` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=33784 DEFAULT CHARSET=latin1

CREATE TABLE `method_timings` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `method` varchar(255) DEFAULT NULL,
  `batch_size` int(11) DEFAULT NULL,
  `timing` int(11) DEFAULT NULL,
  `os` varchar(255) DEFAULT NULL,
  `browser` varchar(255) DEFAULT NULL,
  `version` varchar(255) DEFAULT NULL,
  `user_agent` varchar(255) DEFAULT NULL,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=28849 DEFAULT CHARSET=latin1

(user_agent 使用正则表达式从一小部分可识别值中分解为浏览器、版本和操作系统;我保留原始用户代理字符串以防万一。)

我有一个这样的查询,它告诉我每个非伪造浏览器/版本/方法元组的平均时间:

select c, avg(bogus) as bog, timing, method, browser, version 
  from browser_tests as b inner join (
    select count(*) as c, round(avg(timing)) as timing, method, 
     browser, version from method_timings 
    group by browser, version, method 
    having c > 10 order by browser, version, timing
  ) as t using (browser, version, method)
  group by browser, version, method 
  having bog < 1 
  order by browser, version, timing;

返回类似:

c  bog  tim  method       browser  version
88 0.8333 184 reuse_insert Chrome 4.0.249.89
18 0.0000 238 mass_insert_width Chrome 4.0.249.89
70 0.0400 246 mass_insert Chrome 4.0.249.89
70 0.0400 327 mass_noinsert Chrome 4.0.249.89
88 0.0556 367 reuse_reinsert Chrome 4.0.249.89
88 0.0556 383 jquery Chrome 4.0.249.89
88 0.0556 863 full_reinsert Chrome 4.0.249.89
187 0.0000 105 jquery Chrome 5.0.307.11
187 0.8806 109 reuse_insert Chrome 5.0.307.11
123 0.0000 110 mass_insert_width Chrome 5.0.307.11
176 0.0000 231 mass_noinsert Chrome 5.0.307.11
176 0.0000 237 mass_insert Chrome 5.0.307.11
187 0.0000 314 reuse_reinsert Chrome 5.0.307.11
187 0.0000 372 full_reinsert Chrome 5.0.307.11
12 0.7500 82 reuse_insert Chrome 5.0.335.0
12 0.2500 102 jquery Chrome 5.0.335.0
[...]

我想修改此查询以仅返回时间最短的浏览器/版本/方法 - 即类似于:

88 0.8333 184 reuse_insert Chrome 4.0.249.89
187 0.0000 105 jquery Chrome 5.0.307.11
12 0.7500 82 reuse_insert Chrome 5.0.335.0
[...]

我怎样才能做到这一点,同时仍然返回时间最短的方法?

我可以在应用程序端过滤它,但我宁愿在 mysql 中这样做,因为它更适合我的缓存。

【问题讨论】:

【参考方案1】:

将所有最小时间放入临时表中

SELECT 
  ID
  ,MIN(Time) AS MinTime 
INTO
  #tempMinTimes
FROM
  TABLE_NAME or (Sub Query)
GROUP BY
  ID

然后在 ID 字段上对这个临时表进行 Inner Join。

编辑 我现在才看到有重复的 ID,您还需要删除方法名称上的重复 ID 或组,然后在您的加入中使用 ID 和方法名称

【讨论】:

我认为您不理解我正在使用的查询。没有“重复的 ID”,您的查询将不起作用。 对不起,我没有正确阅读这个问题,我认为 C 是一个 ID,我现在才看到它的计数,但如果你生成一个唯一的 ID,我的查询将起作用

以上是关于sql: 按 x,y,z 分组;返回按 f(z) 最低的 x,y 分组的主要内容,如果未能解决你的问题,请参考以下文章

python按从小到大的顺序输出

三维偏序:CDQ分治

C++ 四元数旋转未按预期工作

JS数组按日期分组

JavaScript函数参数按引用存储[重复]

按一个变量分组,但对 R 中的所有其他变量(均值)进行汇总()