如何忽略PostgreSQL窗口函数中的空值?或者返回列中的下一个非空值

时间:2016-05-26 21:01:35

标签: sql postgresql

假设我有下表:

string token = (string)Session["access_token"];
string email = (string)Session["user_email"];

// Since we have the token locally from the Session, just return it here
OutlookServicesClient client = new OutlookServicesClient(new Uri("https://outlook.office.com/api/v2.0"), async () => { return token; });

client.Context.SendingRequest2 += new EventHandler<SendingRequest2EventArgs>((sender, e) => InsertXAnchorMailboxHeader(sender, e, email));

var contactResults = await client.Me.Contacts
                    .OrderBy(c => c.DisplayName)
                    .Take(2500)
                    .Select(c => new DisplayContact(c))
                    .ExecuteAsync();

foreach (DisplayContact displayContact in contactResults.CurrentPage)
    System.Diagnostics.Debug.WriteLine(displayContact);

我需要另一列指示每行的下一个非空COL1值,因此结果如下所示:

 | User_id |   COL1   | COL2 |
 +---------+----------+------+
 | 1       |          | 1    |
 | 1       |          | 2    | 
 | 1       |   2421   |      | 
 | 1       |          | 1    | 
 | 1       |   3542   |      | 
 | 2       |          | 1    |
 | User_id |   COL1   | COL2 | COL3 |
 +---------+----------+------+------
 | 1       |          | 1    | 2421 |
 | 1       |          | 2    | 2421 |
 | 1       |   2421   |      |      |
 | 1       |          | 1    | 3542 |
 | 1       |   3542   |      |      |
 | 2       |          | 1    |      |

可行,但我使用的PostgreSQL并不支持ignore nulls子句。

任何建议的解决方法?

5 个答案:

答案 0 :(得分:5)

如果按顺序添加条件中的条件,您仍然可以使用窗口函数来执行此操作:

select
   first_value(COL1) 
   over (
     partition by user_id 
     order by case when COL1 is not null then 0 else 1 end ASC, COL2 
     rows unbounded following
   ) 
from table

这将首先使用非空值。

但是,由于数据库必须对其他条件进行排序,因此可能无法很好地执行跳过空值的性能。

答案 1 :(得分:4)

我也有同样的问题。其他解决方案可能有效,但我必须为我需要的每一行构建多个窗口。

您可以尝试以下代码段:https://wiki.postgresql.org/wiki/First/last_(aggregate)

如果您创建聚合,则可以使用它们:

SELECT 
first(COL1) over (partition by user_id order by COL2 rows unbounded following) 
FROM table;

答案 2 :(得分:1)

使用相关子查询总是尝试过的方法:

select t.*,
       (select t2.col1
        from t t2
        where t2.id >= t.id and t2.col1 is not null
        order by t2.id desc
        fetch first 1 row only
       ) as nextcol1
from t;

答案 3 :(得分:0)

希望这会有所帮助,

stime=$(date --date "$time" +%s)

由colA排序,如果colA具有NULL值,则由colB排序。

答案 4 :(得分:0)

您可以使用COALESCE()功能。对于您的查询:

SELECT 
first_value(COALESCE(COL1)) over (partition by user_id order by COL2 rows unbounded following) 
FROM table;

但是我不明白使用COL2排序的原因是什么,因为该行的COL2值为空:

 | User_id |   COL1   | COL2 |
 +---------+----------+------+
 | 1       |          | 1    |
 | 1       |          | 2    | 
 | 1       |   2421   |      | <<--- null?
 | 1       |          | 1    | 
 | 1       |   3542   |      | <<--- null?
 | 2       |          | 1    |