我最近在调查一个问题,其中写入某个dbs表的行的百分比在列中不应为null。当通过其timestamp列对该表进行排序时,我注意到具有空值的行不是随机分散的,而是以大块的形式出现。有数千行,该列为null,后面跟着数千行有效值的行,依此类推。如下所示。
我想调查这些波段的边界发生了什么,其中列从null切换到非null,反之亦然。在调试问题时,查找时间模式或围绕这些开关的数据似乎非常有用。
我想不出让sql只选择这些行的方法,所以我最终编写了一个快速程序来处理数据并返回我想要的内容。请参阅下面的伪代码以演示算法。
resultSet = db.query("select * from table t order by t.timestamp")
prevRow = null
// for simplicity, let's assume there's always at least 2 rows
currentRow = resultSet.next()
nextRow = resultSet.next()
while(resultSet.hasNext())
// if the null state of column we care about has changed around this current row
if(hasNullColumn(prevRow) != hasNullColumn(nextRow)) printRow(currentRow)
prevRow = currentRow;
currentRow = nextRow;
nextRow = resultSet.next();
但我真的很好奇是否有办法编写一个只返回上述逻辑打印的行的SQL查询?那可能吗?
答案 0 :(得分:0)
假设有一个唯一的id列,并且有趣的是它不跟踪timestamp列的增加。还假设没有相同的时间戳。
select pt.* from
(Select max(ptime) as prevtime,min(ntime) as nextime from
((Select timestamp as ptime) as prev,
(Select timestamp as ntime) as next
where prev.ptime < next.ntime and prev.id<>next.id) as s1 group by ptime, ntime) as pn
inner join
t as pt on pn.prevtime=pt.timestamp inner join
t as nt on pn.nexttime=nt.timestamp
where pt.ncol!=nt.ncol;
说明:s1提供彼此之前和之后的成对时间。 pn将它们分组以获得所有相邻时间对的列表。 pt在pn中提供上一次的其余列,并且nt提供下一次的其余列。当我命名为ncol的列切换值时,前一行会吐出到结果集中。如果有多个非空值并且只有在找到null和非null之间的切换时才感兴趣,那么将pt.ncol!= nt.ncol更改为isnull(pt.ncol)!= isnull(nt.ncol)。