首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >SELECT子句中的合并函数

SELECT子句中的合并函数
EN

Stack Overflow用户
提问于 2016-12-11 17:37:07
回答 2查看 2.8K关注 0票数 2

问题:是根据id顺序从表中找到最后一个非空值,在这里可以找到http://sqlmag.com/t-sql/last-non-null-puzzle

代码语言:javascript
运行
复制
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);

期望产出:

代码语言:javascript
运行
复制
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中的代码

代码语言:javascript
运行
复制
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列中的第一个值。我可能错了。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 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用户变量)解决这个问题:

代码语言:javascript
运行
复制
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用户变量来解决这个问题:

代码语言:javascript
运行
复制
SELECT id, col1, @lastval := COALESCE(col1, @lastval) AS lastval
FROM (SELECT @lastval := NULL) AS _init 
CROSS JOIN Score
ORDER BY id;

我将避免您在下面的评论中发布的查询,因为它使用的是关联子查询。相关子查询通常不利于性能。

票数 3
EN

Stack Overflow用户

发布于 2016-12-11 17:52:13

我没有完全搞清楚你要做什么,而且我也不确定它是否能在mysql上工作,但是这个可以在tsql上工作。我希望它能帮上忙

代码语言:javascript
运行
复制
    SELECT s1.id, COALESCE(min(s2.col1),0) FROM score s1 
    JOIN score s2 ON s1.id >= s2.id GROUP BY s1.id
    ORDER BY s1.id, min(s2.col1) DESC
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41089036

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档