Sql 按用户选择每列的最后一个值,这是最简单的方法

Sql 按用户选择每列的最后一个值,这是最简单的方法,sql,null,Sql,Null,这是a的扩展版本。我已经发布了一个新的问题,建议我这样做。(在人们回答了我的第一个问题后,我意识到我其实想要这个) 具有以下数据(空白表示为空): 如何以最简单的方式为所有用户获取每列的最后一个非空值?因此,给定数据的结果为: User ColA ColB ColC 1 11 1 20 2 6 8 10 我没有发现太多类似于我描述的功能是COALESCE,但在我的例子中它并没有像预期的那样工作 注意:如果可能,标准SQ

这是a的扩展版本。我已经发布了一个新的问题,建议我这样做。(在人们回答了我的第一个问题后,我意识到我其实想要这个)

具有以下数据(空白表示为空):

如何以最简单的方式为所有用户获取每列的最后一个非空值?因此,给定数据的结果为:

User  ColA    ColB    ColC
1     11      1       20
2     6       8       10
我没有发现太多类似于我描述的功能是
COALESCE
,但在我的例子中它并没有像预期的那样工作

注意:如果可能,标准SQL,否则为PostgreSQL。相关列的计数可能会发生变化,因此最好采用不与这三个特定列绑定的解决方案。

“标准”SQL 与我在上一个问题上发布的内容类似,在标准SQL中,a是一种优雅且可能是最快的方法,尤其是对于每个用户的多行

WITH RECURSIVE t AS (
   SELECT row_number() OVER (PARTITION BY usr ORDER  BY id DESC) AS rn
         ,usr, cola, colb, colc
   FROM   tbl
   )

   , x AS (
   SELECT rn, usr, cola, colb, colc
   FROM   t
   WHERE  rn = 1

   UNION ALL
   SELECT t.rn, t.usr
        , COALESCE(x.cola, t.cola)
        , COALESCE(x.colb, t.colb)
        , COALESCE(x.colc, t.colc)
   FROM   x
   JOIN   t USING (usr)
   WHERE  t.rn = x.rn + 1
   AND    (x.cola IS NULL OR x.colb IS NULL OR x.colc IS NULL)
   )
SELECT DISTINCT ON (usr)
       usr, cola, colb, colc
FROM   x
ORDER  BY usr, rn DESC;

唯一的非标准元素是上的
DISTINCT,它是标准中
DISTINCT
的扩展。对于标准SQL,将最后的
SELECT
替换为以下内容:

SELECT usr
      ,max(cola) As cola
      ,max(colb) As colb
      ,max(colc) As colc
FROM   x
GROUP  BY usr
ORDER  BY usr;
“标准SQL”的请求用途有限。该标准仅存在于纸面上。没有一个RDBMS实现100%的标准SQL——这也将是毫无意义的,因为该标准在这里和那里包含了无意义的部分。可以说,PostgreSQL的实现是最接近标准的实现之一

PL/pgSQL函数 此解决方案是特定于PostgreSQL的,但性能应该很好

我在上面小提琴所示的同一张桌子上构建

CREATE OR REPLACE FUNCTION f_last_nonull_per_user()
RETURNS SETOF tbl AS
$func$
DECLARE
   _row tbl;  -- table name can be used as row type
   _new tbl;
BEGIN

FOR _new IN
   SELECT * FROM tbl ORDER BY usr, id DESC
LOOP
   IF _new.usr = _row.usr THEN 
      _row.id := _new.id;   -- copy only id
      IF _row.cola IS NULL AND _new.cola IS NOT NULL THEN
         _row.cola := _new.cola; END IF;   -- only if no value found yet
      IF _row.colb IS NULL AND _new.colb IS NOT NULL THEN
         _row.colb := _new.colb; END IF;
      IF _row.colc IS NULL AND _new.colc IS NOT NULL THEN
         _row.colc := _new.colc; END IF;
   ELSE
      IF _new.usr <> _row.usr THEN  -- doesn't fire on first row
         RETURN NEXT _row;
      END IF;   
      _row := _new;  -- remember row for next iteration
   END IF;
END LOOP;

RETURN NEXT _row;  -- return row for last usr

END
$func$ LANGUAGE plpgsql;

返回整行-包括我们需要填充所有列的min
id

此查询很容易转换为MS SQL。如果您需要更具体的内容,请添加评论。Mysql查询:

SELECT
t1.User,
(SELECT ColA 
           FROM Table1
           WHERE ColA is not null
           AND Table1.User = t1.User
           ORDER BY ID DESC
           LIMIT 1 ) as ColA,
(SELECT ColB 
           FROM Table1
           WHERE ColB is not null
           AND Table1.User = t1.User
           ORDER BY ID DESC
           LIMIT 1 ) as ColB,
(SELECT ColC 
           FROM Table1
           WHERE ColC is not null
           AND Table1.User = t1.User
           ORDER BY ID DESC
           LIMIT 1 ) as ColC
FROM Table1 t1
GROUP BY t1.User
结果:

| USER | COLA | COLB | COLC |
-----------------------------
|    1 |   11 |    1 |   20 |
|    2 |    6 |    8 |   10 |

哪种关系数据库管理系统?SQL Server、Oracle等?任何,我更喜欢标准SQL,或者PostgreSQL。你说的“标准SQL”是指MS SQL Server吗?哪个版本?您能提供创建表和插入的脚本吗?可以用于测试。@JeradRose-标准SQL表示符合的SQL。
SELECT
t1.User,
(SELECT ColA 
           FROM Table1
           WHERE ColA is not null
           AND Table1.User = t1.User
           ORDER BY ID DESC
           LIMIT 1 ) as ColA,
(SELECT ColB 
           FROM Table1
           WHERE ColB is not null
           AND Table1.User = t1.User
           ORDER BY ID DESC
           LIMIT 1 ) as ColB,
(SELECT ColC 
           FROM Table1
           WHERE ColC is not null
           AND Table1.User = t1.User
           ORDER BY ID DESC
           LIMIT 1 ) as ColC
FROM Table1 t1
GROUP BY t1.User
| USER | COLA | COLB | COLC |
-----------------------------
|    1 |   11 |    1 |   20 |
|    2 |    6 |    8 |   10 |