问题:是根据id顺序从表中找到最后一个非空值,在这里可以找到http://sqlmag.com/t-sql/last-non-null-puzzle
CREATE TABLE Score(`id` int, `col1` INT NULL);
INSERT INTO Score
(`id`, `col1`)
VALUES
(2, NULL),
(3, 10),
(5, -1),
(7, NULL),
(11, NULL),
(13, -12),
(17, NULL),
(19, NULL),
(23, 1759);期望产出:
id col1 lastval
----------- ----------- -----------
2 NULL NULL
3 10 10
5 -1 -1
7 NULL -1
11 NULL -1
13 -12 -12
17 NULL -12
19 NULL -12
23 1759 1759我在SQLFiddle MySQL 5.6中的代码
SELECT s1.id, COALESCE(s2.col1)
FROM score s1 JOIN score s2
ON s1.id >= s2.id
GROUP BY s1.id
ORDER BY s1.id, s2.id DESC据我了解,合并给出了列表中遇到的第一个非空值。但它为所有列都提供了(null)。你能指出为什么COALESCE不能工作吗?另外,我意识到删除COALESCE也应该回答这个问题,因为GROUP BY子句返回s2.col1列中的第一个值。我可能错了。
发布于 2016-12-11 18:00:44
COALESCE()在其参数列表中返回第一个非空值。对于分组行集上的相同表达式,不存在将合并()应用于相同表达式的隐式行为。它不是像SUM()或GROUP_CONCAT()这样的聚合函数。
就像你正在做的那样,把它和一个参数一起使用是没有意义的,因为你只给了它一个参数。因此,这与将s2.col1放入查询的select列表中完全一样,而不将其放入COALESCE()调用中。
然后,在按函数引用组中的非分组列时,您将看到MySQL的默认行为: MySQL从组中的某一行任意选择s2.col1的值。实际上,这是组中按索引顺序读取的第一行,但不应该依赖于此。
因此,在您的示例中,您的联接将每一行s1连接到所有行s2,这样s2.id就更早了。每个组都包含表中的第一行,其中包含s2.id=2。该行对于col1有一个NULL。
我读了一遍你想要解决的SQL难题。在MySQL中,这将是特别尴尬的,因为MySQL不支持窗口函数。
在这些情况下,解决方案通常包括使用MySQL 用户定义变量,在查询遍历表中的行时更改值。这可能会很棘手。
下面是我如何以可移植的方式(没有MySQL用户变量)解决这个问题:
SELECT s1.id, s1.col1, s2.col1 as lastval
FROM Score AS s1
LEFT OUTER JOIN Score AS s2 ON s2.id <= s1.id AND s2.col1 IS NOT NULL
LEFT OUTER JOIN Score AS s3 ON s3.id > s2.id AND s3.id <= s1.id AND s3.col1 IS NOT NULL
WHERE s3.id IS NULL
ORDER BY s1.id;下面是如何使用MySQL用户变量来解决这个问题:
SELECT id, col1, @lastval := COALESCE(col1, @lastval) AS lastval
FROM (SELECT @lastval := NULL) AS _init
CROSS JOIN Score
ORDER BY id;我将避免您在下面的评论中发布的查询,因为它使用的是关联子查询。相关子查询通常不利于性能。
https://stackoverflow.com/questions/41089036
复制相似问题