পার্টিশনে প্রথমে নন-নাল মান এগিয়ে নিয়ে যাওয়ার জন্য উইন্ডো ফাংশন ব্যবহার করে


12

একটি টেবিল বিবেচনা করুন যা দর্শন রেকর্ড করে

create table visits (
  person varchar(10),
  ts timestamp, 
  somevalue varchar(10) 
)

এই উদাহরণ ডেটা বিবেচনা করুন (টাইমস্ট্যাম্প কাউন্টার হিসাবে সরলীকৃত)

ts| person    |  somevalue
-------------------------
1 |  bob      |null
2 |  bob      |null
3 |  jim      |null
4 |  bob      |  A
5 |  bob      | null
6 |  bob      |  B
7 |  jim      |  X
8 |  jim      |  Y
9 |  jim      |  null

আমি সেই ব্যক্তির সর্বশেষ নন-নাল কিছু মূল্য ভবিষ্যতের পরিদর্শনে এগিয়ে নিয়ে যাওয়ার চেষ্টা করছি যতক্ষণ না সেই মান পরিবর্তিত হয় (অর্থাত্ পরবর্তী নন-নাল হয়ে যায়)।

প্রত্যাশিত ফলাফল সেটটি দেখতে এমন দেখাচ্ছে:

ts|  person   | somevalue | carry-forward 
-----------------------------------------------
1 |  bob      |null       |   null
2 |  bob      |null       |   null
3 |  jim      |null       |   null
4 |  bob      |  A        |    A
5 |  bob      | null      |    A
6 |  bob      |  B        |    B
7 |  jim      |  X        |    X
8 |  jim      |  Y        |    Y
9 |  jim      |  null     |    Y

আমার প্রচেষ্টাটি এরকম দেখাচ্ছে:

 select *, 
  first_value(somevalue) over (partition by person order by (somevalue is null), ts rows between UNBOUNDED PRECEDING AND current row  ) as carry_forward

 from visits  
 order by ts

দ্রষ্টব্য: (কিছুটা নাল হয়) বাছাইয়ের উদ্দেশ্যে 1 বা 0 এ মূল্যায়ন করে যাতে আমি পার্টিশনে প্রথম নন-মান পেতে পারি।

উপরেরটি আমাকে পরে ফলাফল দেয় না।


আপনি কি কেবলমাত্র pg_dumpকোনও পিএসকিএল আউটপুটে ডেটা পেস্ট করার চেয়ে টেস্টের ডেটা এবং টেবিলের জন্য স্কিমা পেস্ট করতে পারবেন? pg_dump -t table -d databaseআমাদের তৈরি এবং COPYআদেশগুলি দরকার।
ইভান ক্যারল


1
@a_horse_with_no_name যা উত্তর পাওয়ার যোগ্য।
ypercubeᵀᴹ

উত্তর:


12

নিম্নলিখিত কোয়েরি পছন্দসই ফলাফল অর্জন করে:

select *, first_value(somevalue) over w as carryforward_somevalue
from (
  select *, sum(case when somevalue is null then 0 else 1 end) over (partition by person order by id ) as value_partition
  from test1

) as q
window w as (partition by person, value_partition order by id);

নাল কেস স্টেটমেন্টটি নোট করুন - যদি IGNORE_NULL পোস্টগ্রিজ উইন্ডো ফাংশন দ্বারা সমর্থিত হয় তবে এটির প্রয়োজন হবে না (@ ইয়পারক्यूबᵀᴹ দ্বারা উল্লিখিত)


5
এছাড়াও সহজcount(somevalue) over (...)
ypercubeᵀᴹ

5

সমস্যাটি ফাঁক এবং দ্বীপপুঞ্জের সমস্যার মধ্যে রয়েছে in এটি দুঃখের বিষয় যে পোস্টগ্র্রেস এখনও IGNORE NULLউইন্ডো ফাংশনগুলিতে যেমন বাস্তবায়িত করেনি FIRST_VALUE(), অন্যথায় এটি আপনার তদন্তের সাধারণ পরিবর্তনের সাথে তুচ্ছ।

উইন্ডো ফাংশন বা পুনরাবৃত্ত সিটিই ব্যবহার করে এর সমাধানের জন্য সম্ভবত অনেকগুলি উপায় রয়েছে।

এটি সবচেয়ে কার্যকর উপায় কিনা তা নিশ্চিত নন তবে একটি পুনরাবৃত্ত সিটিই সমস্যার সমাধান করে:

with recursive 
    cf as
    (
      ( select distinct on (person) 
            v.*, v.somevalue as carry_forward
        from visits as v
        order by person, ts
      ) 
      union all
        select 
            v.*, coalesce(v.somevalue, cf.carry_forward)
        from cf
          join lateral  
            ( select v.*
              from visits as v
              where v.person = cf.person
                and v.ts > cf.ts
              order by ts
              limit 1
            ) as v
            on true
    )
select cf.*
from cf 
order by ts ;

এটি প্রকৃতপক্ষে সমস্যার সমাধান করতে পারে তবে এটি হওয়া দরকারের চেয়ে জটিল। আমার উত্তর নীচে দেখুন
ম্যাক্সট্রিয়ালফায়ার

1
হ্যাঁ, আপনার উত্তরটি ভাল মনে হচ্ছে!
ypercubeᵀᴹ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.