选择最近的邻居

时间:2015-07-31 05:24:01

标签: sql postgresql window-functions

考虑以下数据:

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

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

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

我一直在玩窗口功能,我很确定它可以实现,但解决方案让我望而却步。

有什么想法吗?

3 个答案:

答案 0 :(得分:1)

你是对的,窗口功能是你正在寻找的。以下是如何完成的(with部分用于定义表格,因此您可能不会需要它):

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";

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

答案 1 :(得分:-1)

我正在为你开发一个解决方案,但是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
;

我正在努力的小提琴就在这里:http://sqlfiddle.com/#!15/acbc2/1

答案 2 :(得分:-2)

虽然我确信它有可能制作出一些非常复杂且嵌套的语句来做你想做的事情,但我想说,有时,用常规编程语言编写脚本比如python / ruby​​ / java更好。遍历数据库表并进行所需的任何更改。

这将是一个更加可维护的,并且您希望每次需要对其进行任何更改时都必须重新架构整个事物(例如使用3个最近的邻居,或者更改“最近邻居”的定义)< / p>