使用下表:
A | B | C | ts
--+------+------+------------------
1 | null | null | 2016-06-15 10:00
4 | null | null | 2016-06-15 11:00
4 | 9 | null | 2016-06-15 12:00
5 | 1 | 7 | 2016-06-15 13:00
如何在N行的运行窗口中选择每列的第一个非空值? “第一个”由列ts
中的时间戳顺序定义。查询上表将导致:
A | B | C
--+---+---
1 | 9 | 7
答案 0 :(得分:15)
窗口函数first_value()
允许一个相当简短和优雅的解决方案:
SELECT first_value(a) OVER (ORDER BY a IS NULL, ts) AS a
, first_value(b) OVER (ORDER BY b IS NULL, ts) AS b
, first_value(c) OVER (ORDER BY c IS NULL, ts) AS c
FROM t
LIMIT 1;
a IS NULL
评估为TRUE
或FALSE
。 FALSE
之前TRUE
排序。这样,非空值首先出现。接下来按ts
排序(您评论的时间戳列),然后您就可以在一个SELECT
中找到它。
如果Postgres支持IGNORE NULLS
,这会更简单。 The manual:
SQL标准定义了
RESPECT NULLS
或IGNORE NULLS
选项lead
,lag
,first_value
,last_value
和nth_value
。这不是 在PostgreSQL中实现:行为总是与 标准的默认值,即RESPECT NULLS
。
该领域关于标准SQL的少数遗漏之一。
db<>小提琴here
SQL Fiddle.
答案 1 :(得分:3)
您应该定义一个订单(主键或其他内容)以获取FIRST非空值。所以我使用ID
列来排序表格中的行。
select
(select A from t where A is not null ORDER BY id LIMIT 1),
(select b from t where b is not null ORDER BY id LIMIT 1),
(select c from t where c is not null ORDER BY id LIMIT 1)
答案 2 :(得分:1)
您可以使用window functions执行此操作。我已将结果分为两部分,然后将此分区用于row_number
window function
然后,使用基本case
来获取row_number
为1
并且其中包含not null
值的
SELECT
max ( CASE
WHEN a_row_num = 1 AND a IS NOT NULL THEN a
END ) AS A,
max ( CASE
WHEN b_row_num = 1 AND B IS NOT NULL THEN B
END ) AS B,
max ( CASE
WHEN c_row_num = 1 AND C IS NOT NULL THEN C
END ) AS C
FROM
(
SELECT
a,
row_number ( ) over ( partition BY a IS NULL ORDER BY ID ) a_row_num,
b,
row_number ( ) over ( partition BY b IS NULL ORDER BY ID ) b_row_num,
c,
row_number ( ) over ( partition BY c IS NULL ORDER BY ID ) c_row_num
FROM
test
) AS sub_query
<强>输出:强>
| A | B | C |
|---|---|---|
| 1 | 9 | 7 |
注意:我添加了id
字段,这有助于了解哪些记录首次插入,我们在窗口函数中按升序使用
答案 3 :(得分:0)
不确定我是否正确地提出了问题
因为它看起来很简单。
试试这个查询
SQL小提琴:http://sqlfiddle.com/#!11/ac585/8
WITH t0 AS
(
SELECT A FROM
TableName t0
WHERE (A IS NOT NULL)
ORDER BY ID ASC
LIMIT 1
),
t1 AS
(
SELECT B FROM
TableName
WHERE (B IS NOT NULL)
ORDER BY ID ASC
LIMIT 1
),
t2 AS
(
SELECT C FROM
TableName
WHERE (C IS NOT NULL)
ORDER BY ID ASC
LIMIT 1
)
SELECT t0.A, t1.B, t2.C
FROM
t0
JOIN t1 ON 1=1
JOIN t2 ON 1=1