丢失记录的线索功能

时间:2019-05-01 07:29:50

标签: mysql sql snowflake

我正在使用以下查询

 select  id,
         number_sequ,
         startvalue
         lead(startvalue,1,0) over (partition by id order by number_sequ) AS End_value
 from mytable

填充以下输出

id             number_sequ   startvalue       End_value
----            -----       ----------       -----------
AAA             1             30              20
AAA             2             20              10
AAA             4             10              15
AAA             5             15              0
BBB             1             12              23
BBB             3             23              34
BBB             4             34              0

但是依序缺少记录

id         number_sequ   startvalue       End_value
----         -----       ----------       -----------
AAA          3           
BBB          2

我尝试了多种方法来找出Sequence中缺少的数字并尝试插入0个值。之后,我可以使用Lead功能。找不到有效的方法

INSERT INTO mytable (id, number_sequ, startvalue)
    select id ,number_sequ ,'0'
    from mytable
    where (some condition to specify missing data)

任何人都可以帮助我解决上述问题。

3 个答案:

答案 0 :(得分:0)

您可以通过以下方法获取缺失值:生成所有可能的值,然后过滤掉存在的值。

select i.id, n.n, 0 as start_value
from (select id, min(number_seq) as min_ns, max(number_seq) as max_ns
      from mytable
      group by id
     ) i join
     (select row_number() over (partition by number_seq) as n
      from mytable
     ) n
     on n.n <= i.max_ns left join -- just a bunch of numbers
     mytable t
     on t.id = i.id and
        t.number_seq = n.n 
where t.id is null;

您可以在insert之前弹出select,将这些值插入表中。

请注意,这将使用原始数据生成您需要的序列号。因此,假设您的表有足够的行来容纳所需的数字。

答案 1 :(得分:0)

如果缺失值始终在现有值之间,则可以使用雪花的JavaScript UDTFs

例如,这是一个在序列中查找空位的函数,然后我们使用它来生成“空”行:

create or replace table x(id int, seq int, startVal int) as select * from
values(1,1,11),(1,2,12),(1,4,14),(2,2,22),(2,5,25);


CREATE OR REPLACE FUNCTION find_gaps(SEQ float)
RETURNS TABLE (GAP float)
LANGUAGE JAVASCRIPT
AS '
  {
    initialize: function(argumentInfo, context) {
      this.lastRow = null;
    },
    processRow: function (row, rowWriter, context) {
      let curRow = row.SEQ;
      if (this.lastRow == null || this.lastRow + 1 == curRow) {
        this.lastRow = curRow;
      } else {
        while (this.lastRow + 1 < curRow) {
          this.lastRow++;
          rowWriter.writeRow({GAP: this.lastRow});
        }
      }
    }
  }'
;

select id, seq, startVal from x 
union all  
select id, gap, 0 from x,     
  table(find_gaps(seq::float) 
    over (partition by id order by seq));

----+-----+----------+
 ID | SEQ | STARTVAL |
----+-----+----------+
 1  | 1   | 11       |
 1  | 2   | 12       |
 1  | 4   | 14       |
 2  | 2   | 22       |
 2  | 5   | 25       |
 2  | 3   | 0        |
 2  | 4   | 0        |
 1  | 3   | 0        |
----+-----+----------+

您也可以使用此功能的变体,例如如果您知道每个ID的值范围,则也可以输入预期的最小值/最大值。另外,如果您的输入包含NULL值,则可能需要一些特殊的东西(但是-结果应该是什么?:))

答案 2 :(得分:0)

除了建议的解决方案之外,如果您仍然希望使用Lead功能,

Lead函数分析具有值的数据,基于分区的结果可以具有空值,但用于分析的数据应具有值。我认为,您所做的是正确的,将缺失的序列包括在结果中。

http://www.mysqltutorial.org/mysql-window-functions/mysql-lead-function/