MySQL在每个组中选择第一个,第二个和最后一个值的最佳方法

林家祥

我正在尝试使用MySQL获取表中每个组的第一个,第二个和最后一个值。我的数据行是这样的:

userID    purchaseTime
----------------------
1         2018-01-01
1         2018-01-02
1         2018-01-03
1         2018-01-04
2         2018-02-01
2         2018-02-02
3         2018-03-01

预期结果将是:

userID    first         second        last
------------------------------------------------
1         2018-01-01    2018-01-02    2018-01-04
2         2018-02-01    2018-02-02    2018-02-02
3         2018-03-01    null          2018-03-01

搜寻了半天后,我只能找出一种愚蠢的方式来分别执行以下两个查询,然后通过服务器端代码合并结果:

//get 1st, 2nd values 
SELECT userID, purchaseTime
FROM   purchaseLog t1
WHERE 
    (
        SELECT  COUNT(*) 
        FROM    purchaseLog t2
        WHERE t2.userID = t1.userID AND 
              t2.purchaseTime<= t1.purchaseTime
    ) <= 2 order by t1.userID , t1.purchaseTime;

//get last value
SELECT max(purchaseTime) FROM purchaseTime GROUP BY userID 

我非常确定,必须有一种更优雅的方法来一次性获得结果。谁能帮助我达到要求?谢谢你们!

reaanb

以下代码未经测试,但可以为您提供一个好主意:

SELECT
    t1.userID,
    t1.purchaseTime AS first,
    t2.purchaseTime AS `second`,
    t4.purchaseTime AS last
FROM purchaseLog t1
LEFT JOIN purchaseLog t0 ON t1.userID = t0.userID AND t0.purchaseTime < t1.purchaseTime
LEFT JOIN purchaseLog t2 ON t1.userID = t2.userID AND t1.purchaseTime < t2.purchaseTime
LEFT JOIN purchaseLog t3 ON t1.userID = t3.userID AND t1.purchaseTime < t3.purchaseTime
                        AND t3.purchaseTime < t2.purchaseTime
JOIN purchaseLog t4 ON t1.userID = t4.userID AND t1.purchaseTime <= t4.purchaseTime
LEFT JOIN purchaseLog t5 ON t1.userID = t5.userID AND t4.purchaseTime < t5.purchaseTime
WHERE t0.purchaseTime IS NULL AND t3.purchaseTime IS NULL AND t5.purchaseTime IS NULL

让我一步步分解一下:

首先,获取所有不存在相同userID的较早行的行:

SELECT
    t1.userID,
    t1.purchaseTime AS first
FROM purchaseLog t1
LEFT JOIN purchaseLog t0 ON t1.userID = t0.userID AND t0.purchaseTime < t1.purchaseTime
WHERE t0.purchaseTime IS NULL

接下来,我得到所有purchaseTime大于第一个purchaseTime的行,在这两个行之间没有没有purchaseTime的行:

SELECT
    t1.userID,
    t2.purchaseTime AS `second`
FROM purchaseLog t1
LEFT JOIN purchaseLog t2 ON t1.userID = t2.userID AND t1.purchaseTime < t2.purchaseTime
LEFT JOIN purchaseLog t3 ON t1.userID = t3.userID AND t1.purchaseTime < t3.purchaseTime
                        AND t3.purchaseTime < t2.purchaseTime
WHERE t3.purchaseTime IS NULL

最后,我获得了purchaseTime大于或等于第一个不大于purchaseTime的行:

SELECT
    t1.userID,
    t4.purchaseTime AS last
FROM purchaseLog t1
JOIN purchaseLog t4 ON t1.userID = t4.userID AND t1.purchaseTime <= t4.purchaseTime
LEFT JOIN purchaseLog t5 ON t1.userID = t5.userID AND t4.purchaseTime < t5.purchaseTime
WHERE t5.purchaseTime IS NULL

将它们全部组合成一个查询即可得到以上答案。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

在CSS中选择第二个tr的第一个td

从MySQL中的最后一个条目中选择第二个

在表单中,选择第二个表和第一个表

Javascript:获取第一个和第二个斜杠的值

使用ajax和jQuery根据烧瓶中第一个下拉列表中选择的值填充第二个下拉列表

填充在第一个选择中选择的选项的第二个选择 deoending

隐藏第二个属性选择字段,直到在Woocommerce中选择“第一个”为止

优化更新第一个、最后一个和倒数第二个排名值

VBA:使用.Find方法查找第一个和第二个值出现

Doctrine 从与第一个表匹配的第二个表中选择最后一条记录

在嵌套列表中从第一个列表中选择第一个元素,从第二个列表中选择第二个元素,依此类推

SQL:选择第一列的第一个匹配项,第二个值不同

如何在Excel列表中选择第一个(第二个,...)非空元素?

PostgreSQL:从第一个表中选择或替换为第二个表中的数据

当第二个 td 包含单词时,在第一个 td 中选择输入

选择第二个复选框也将选择第一个

根据第一个选择设置第二个选择的选项

:eq不选择第二个div而选择第一个| jQuery的

MySQL-加入2个表时在第二个表中选择最后一个条目

在选择第一个引导程序选择时更新第二个引导程序选择的值

第一组的唯一值,然后是第一个和第二个,依此类推

使用第一个查询获取每个线程的第一个值并使用该值执行第二个查询

执行2个mysql查询,第二个基于第一个

将值从第一个选择添加到第二个选择

如何使用Zend Form中的JQuery从第一个下拉选择中的下拉菜单中选择第二个值

根据第二个值找到内部数组的第一个值

查找第一个值并返回列表中的第二个值

根据第二个值返回数组的第一个值

在第二个查询的值中使用第一个查询的值