How do I select from a table rows with no nulls?

Viewed 165

In KDB, I have a query of the form:

select from t where not null a, not null b

Is it possible to select rows that contain no nulls, rather than specifying a and b?

3 Answers

For a simple t then something like the below may work:

q)t:([]a:1 2 3 4;b:1 2 0N 4;c:1 2 3 0N)
q)t
a b c
-----
1 1 1
2 2 2
3   3
4 4
q)t where not any flip null t
a b c
-----
1 1 1
2 2 2

This will check all columns for nulls and only return the indices for those columns with no nulls. For tables with columns containing strings, or lists of lists, this will fail and you will need more in-depth logic.

Solution proposed by @SeanHehir is spot on (+1 from me).
Note that it won't work if table t is keyed though. To solve for that:

k:keys t;
xkey[k;t where not any flip null t:0!t]

Here's a simple solution to support string columns (null value is "") and complex lists (assuming null value is always ()).

q)t:([]a:0N 1 2 4;b:("abc";"";"def";"ghi");c:(1 2 3;3 4 5;();6 7 8))
q)t
a b     c    
-------------
  "abc" 1 2 3
1 ""    3 4 5
2 "def" ()   
3 "ghi" 6 7 8

findNonNull:{
    f:exec c!{$[x="C";like[;""];x in .Q.a;null;(~\:)[;()]]} each t from meta x;
    x where not any f@'flip x
};

q)findNonNull t
a b     c    
-------------
4 "ghi" 6 7 8

First, a mapping from column name to nullable function using the meta. The cold $ can be extended to suit your specific requirements.

q)exec c!{$[x="C";like[;""];x in .Q.a;null;(~\:)[;()]]} each t from meta t
a| ^:
b| like[;""]
c| ~\:[;()]

These are then applied to the corresponding column in the flipped table, before finding only non-null rows.

Related