অনুমান / স্পষ্টকরণ
এর মধ্যে পার্থক্য করার infinityএবং উপরের আবদ্ধ ( upper(range) IS NULL) খোলার দরকার নেই । (আপনি এটি যে কোনও উপায়ে পেতে পারেন, তবে এটি সহজ উপায় simp)
যেহেতু dateএকটি পৃথক প্রকারের, তাই সমস্ত রেঞ্জের ডিফল্ট [)সীমানা রয়েছে।
প্রতি ডকুমেন্টেশন:
বিল্ট-ইন পরিসীমা ধরনের int4range, int8rangeএবং daterangeসব ব্যবহার ক্যানোনিকাল ফর্ম নিম্ন আবদ্ধ এবং বাদ উপরের আবদ্ধ অন্তর্ভুক্ত; যে [),।
অন্যান্য ধরণের জন্য (যেমন tsrange!) আমি যদি সম্ভব হয় তবে একই প্রয়োগ করবো:
খাঁটি এসকিউএল সহ সমাধান
স্পষ্টতার জন্য সিটিই সহ:
WITH a AS (
SELECT range
, COALESCE(lower(range),'-infinity') AS startdate
, max(COALESCE(upper(range), 'infinity')) OVER (ORDER BY range) AS enddate
FROM test
)
, b AS (
SELECT *, lag(enddate) OVER (ORDER BY range) < startdate OR NULL AS step
FROM a
)
, c AS (
SELECT *, count(step) OVER (ORDER BY range) AS grp
FROM b
)
SELECT daterange(min(startdate), max(enddate)) AS range
FROM c
GROUP BY grp
ORDER BY 1;
বা , সাবকিউয়ের সাথে একই, দ্রুত তবে কম সহজে পড়তে হবে:
SELECT daterange(min(startdate), max(enddate)) AS range
FROM (
SELECT *, count(step) OVER (ORDER BY range) AS grp
FROM (
SELECT *, lag(enddate) OVER (ORDER BY range) < startdate OR NULL AS step
FROM (
SELECT range
, COALESCE(lower(range),'-infinity') AS startdate
, max(COALESCE(upper(range), 'infinity')) OVER (ORDER BY range) AS enddate
FROM test
) a
) b
) c
GROUP BY grp
ORDER BY 1;
বা একটি কম subquery স্তর সঙ্গে, কিন্তু উল্টানো বাছাই ক্রম:
SELECT daterange(min(COALESCE(lower(range), '-infinity')), max(enddate)) AS range
FROM (
SELECT *, count(nextstart > enddate OR NULL) OVER (ORDER BY range DESC NULLS LAST) AS grp
FROM (
SELECT range
, max(COALESCE(upper(range), 'infinity')) OVER (ORDER BY range) AS enddate
, lead(lower(range)) OVER (ORDER BY range) As nextstart
FROM test
) a
) b
GROUP BY grp
ORDER BY 1;
- পুরোপুরি বিপরীত সাজানোর ক্রম পেতে দ্বিতীয় ধাপে উইন্ডোটি সাজান
ORDER BY range DESC NULLS LAST(সহ NULLS LAST) । এটি সস্তা (উত্পাদনের পক্ষে সহজ, প্রস্তাবিত সূচির যথাযথ ক্রমের সাথে মিলে যায়) এবং কোণার ক্ষেত্রে সঠিক হতে হবে ।
rank IS NULL
ব্যাখ্যা করা
a: দ্বারা অর্ডার করার সময় range, উইন্ডো ফাংশন সহ উপরের বাউন্ডের সর্বোচ্চ চলমান গণনা করুন enddate। কেবলমাত্র
সরলকরণের infinityজন্য (বিশেষ কোনও NULL কেস নেই) + /- দিয়ে ন্যূনাল বাউন্ডস (আনবাউন্ডেড) প্রতিস্থাপন করুন ।
b: একই সাজানোর ক্রমে, পূর্ববর্তীটি যদি আমাদের ফাঁক enddateহওয়ার চেয়ে আগের হয় startdateএবং একটি নতুন পরিসর ( step) শুরু করে।
মনে রাখবেন, উপরের সীমাটি সর্বদা বাদ থাকে।
c: grpঅন্য উইন্ডো ফাংশন সহ পদক্ষেপ গণনা করে গ্রুপগুলি ( ) ফর্ম করুন ।
বাইরের SELECTবিল্ডে প্রতিটি গ্রুপের নিম্ন থেকে উপরের সীমানা পর্যন্ত রয়েছে। Voila।
আরও ব্যাখ্যা সহ এসও তে ঘনিষ্ঠভাবে সম্পর্কিত উত্তর:
Plpgsql সহ পদ্ধতিগত সমাধান
যে কোনও টেবিল / কলামের নামের জন্য কাজ করে তবে কেবল টাইপের জন্য daterange।
লুপগুলি সহ পদ্ধতিগত সমাধানগুলি সাধারণত ধীর হয় তবে এই বিশেষ ক্ষেত্রে আমি ফাংশনটি যথেষ্ট গতিযুক্ত হওয়ার আশা করি কারণ এটির জন্য কেবল একটি একক অনুক্রমিক স্ক্যান প্রয়োজন :
CREATE OR REPLACE FUNCTION f_range_agg(_tbl text, _col text)
RETURNS SETOF daterange AS
$func$
DECLARE
_lower date;
_upper date;
_enddate date;
_startdate date;
BEGIN
FOR _lower, _upper IN EXECUTE
format($$SELECT COALESCE(lower(t.%2$I),'-infinity') -- replace NULL with ...
, COALESCE(upper(t.%2$I), 'infinity') -- ... +/- infinity
FROM %1$I t
ORDER BY t.%2$I$$
, _tbl, _col)
LOOP
IF _lower > _enddate THEN -- return previous range
RETURN NEXT daterange(_startdate, _enddate);
SELECT _lower, _upper INTO _startdate, _enddate;
ELSIF _upper > _enddate THEN -- expand range
_enddate := _upper;
-- do nothing if _upper <= _enddate (range already included) ...
ELSIF _enddate IS NULL THEN -- init 1st round
SELECT _lower, _upper INTO _startdate, _enddate;
END IF;
END LOOP;
IF FOUND THEN -- return last row
RETURN NEXT daterange(_startdate, _enddate);
END IF;
END
$func$ LANGUAGE plpgsql;
কল করুন:
SELECT * FROM f_range_agg('test', 'range'); -- table and column name
যুক্তিটি এসকিউএল সমাধানগুলির অনুরূপ, তবে আমরা একক পাস দিয়ে করতে পারি।
এসকিউএল ফিডল।
সম্পর্কিত:
গতিশীল এসকিউএল এ ব্যবহারকারী ইনপুট পরিচালনা করার জন্য সাধারণ ড্রিল:
সূচক
এই প্রতিটি সমাধানের জন্য একটি সাধারণ (ডিফল্ট) বিটি্রি সূচক rangeবড় টেবিলগুলিতে পারফরম্যান্সের জন্য সহায়ক হবে:
CREATE INDEX foo on test (range);
বিটিরি সূচকটি সীমার ধরণের জন্য সীমিত ব্যবহারের জন্য , তবে আমরা প্রাক-সাজানো ডেটা পেতে পারি এবং এমনকি কেবল সূচক-কেবল স্ক্যান করতে পারি।