অনুমান / স্পষ্টকরণ
এর মধ্যে পার্থক্য করার 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);
বিটিরি সূচকটি সীমার ধরণের জন্য সীমিত ব্যবহারের জন্য , তবে আমরা প্রাক-সাজানো ডেটা পেতে পারি এবং এমনকি কেবল সূচক-কেবল স্ক্যান করতে পারি।