select 最近邻

select nearest neighbours

考虑以下数据:

category | index | value
-------------------------
cat 1    | 1     | 2
cat 1    | 2     | 3
cat 1    | 3     |  
cat 1    | 4     | 1
cat 2    | 1     | 5
cat 2    | 2     |  
cat 2    | 3     |  
cat 2    | 4     | 6
cat 3    | 1     |  
cat 3    | 2     |  
cat 3    | 3     | 2 
cat 3    | 4     | 1

我正在尝试填补这些漏洞,以便 hole = avg(value) 个类别中具有非空值的 2 个最近邻居:

category | index | value
-------------------------
cat 1    | 1     | 2
cat 1    | 2     | 3
cat 1    | 3     | 2*
cat 1    | 4     | 1
cat 2    | 1     | 5
cat 2    | 2     | 5.5*
cat 2    | 3     | 5.5* 
cat 2    | 4     | 6
cat 3    | 1     | 1.5*
cat 3    | 2     | 1.5* 
cat 3    | 3     | 2 
cat 3    | 4     | 1

我一直在玩 window 函数,我很确定它可以实现,但我找不到解决方案。

有什么想法吗?

虽然我确信可以创建一些极其复杂的嵌套语句来执行您想要的操作,但我想说的是,有时候,最好用常规编程语言编写脚本,例如 python/ruby/java 遍历数据库 table 并进行所需的任何更改。

这将更易于维护,并且您希望每次需要对其进行任何更改时都必须重新构建整个事物(例如改用 3 个最近的邻居,或更改 [=14= 的定义) ])

我正在为您制定解决方案,但 SQLfiddle 目前出现(内部)错误,因此我无法完成。

像这样的声明应该为您完成更新:

update table1 as t1
set value = 
  (select avg(value)
   from 
   (select value
    from table1 as t3
    where t1.category = t3.category
    and   t3.index in (t1.index - 1, t1.index + 1)
    ) AS T2
   )
where value is null
;

我正在研究的 fiddle 在这里:http://sqlfiddle.com/#!15/acbc2/1

你说得对,window 函数正是你要找的。这是如何完成的(with 部分用于定义 table,因此您可能不需要它):

with dt as
(
    select * from
    (
        values
            ('cat 1', 1, 2),
            ('cat 1', 2, 3),
            ('cat 1', 3, null),
            ('cat 1', 4, 1),
            ('cat 2', 1, 5),
            ('cat 2', 2, null),
            ('cat 2', 3, null),
            ('cat 2', 4, 6),
            ('cat 3', 1, null),
            ('cat 3', 2, null),
            ('cat 3', 3, 1),
            ('cat 3', 4, 2)

    ) tbl ("category", "index", "value")
)
select
        "category",
        "index",
        case
            when "value" is null then (avg("value") over (partition by "category") )
            else "value"
        end
    from dt
    order by "category", "index";

有关 window 功能的更多信息,请参阅 this 页面的 WINDOW Clause 部分。