একটি ব্যাপ্তিতে প্রতিটি তারিখের জন্য একটি জটিল ক্যোয়ারী চালানো


9

আমি অর্ডার একটি টেবিল পেয়েছি

   Column   |            Type             |                      Modifiers                      
------------+-----------------------------+-----------------------------------------------------
 id         | integer                     | not null default nextval('orders_id_seq'::regclass)
 client_id  | integer                     | not null
 start_date | date                        | not null
 end_date   | date                        | 
 order_type | character varying           | not null

ডেটাতে ক্লায়েন্ট_আইডের জন্য অ-ওভারল্যাপিং স্থায়ী অর্ডার এবং মাঝে মাঝে একটি অস্থায়ী আদেশ রয়েছে যা তার স্টার্ট_ডেটের স্থায়ী ক্রমটিকে ওভাররাইড করে যখন তাদের সাথে একটি মেলে ক্লায়েন্ট_আইড থাকে। ওভারল্যাপিং থেকে একই ধরণের অর্ডার রাখতে অ্যাপ্লিকেশন স্তরের প্রতিবন্ধকতা রয়েছে।

 id | client_id | start_date |  end_date  | order_type 
----+-----------+------------+------------+------------
 17 |        11 | 2014-02-05 |            | standing
 18 |        15 | 2014-07-16 | 2015-07-19 | standing
 19 |        16 | 2015-04-01 |            | standing
 20 |        16 | 2015-07-18 | 2015-07-18 | temporary

উদাহরণস্বরূপ, 2015-07-18ক্লায়েন্টে 16 টির ক্রম অর্ডার হিসাবে # 20 এর অর্ডার রয়েছে কারণ এটি স্থায়ী আদেশ # 19 কে ওভাররাইড করে। কিছু হট্টগোলের সাথে আমি একটি তারিখে সক্রিয় অর্ডার আইডির অনুসন্ধানের কার্যকর উপায় খুঁজে পেয়েছি found

    SELECT id from (
      SELECT
        id,
        first_value(id) OVER (PARTITION BY client_id ORDER BY order_type DESC) active_order_id
      FROM orders
      WHERE start_date <= ? and (end_date is null OR end_date >= ?)
    ) active_orders
    WHERE id = active_order_id

আপনি যদি 2015-07-18স্থানধারক হিসাবে এটি নিয়ে প্রশ্ন করেন তবে আপনি পাবেন would

 id 
----
 17
 18
 20

আমার অন্যান্য কিছু ধারণার তুলনায় এই ক্যোয়ারিতে ক্যোয়ারী পরিকল্পনা (যেমন কোনও তারিখে ক্লায়েন্টের জন্য অস্থায়ী আদেশের সংখ্যা গণনা করা সাব কোয়েরিগুলি) বেশ ছোট এবং আমি এতে খুশি। (টেবিলের নকশা, আমি এতে শিহরিত হই না)

এখন, আমার সক্রিয় তারিখের সাথে যোগ হওয়া তারিখের পরিসরের জন্য সমস্ত সক্রিয় অর্ডার খুঁজতে হবে। উদাহরণস্বরূপ, তারিখ পরিসর 2015-07-18থেকে 2015-07-19আমি নিম্নলিখিত ফলাফলের চাই।

active_date | id 
------------+----
 2015-07-18 | 17
 2015-07-18 | 18
 2015-07-18 | 20
 2015-07-19 | 17
 2015-07-19 | 18
 2015-07-19 | 19

অর্ডার 20 ওভাররাইডে 19 টি অর্ডার করুন 2015-07-18তবে চালু নয় 2015-07-19

আমি দেখতে পেলাম যে generate_series()আমি বিভিন্ন তারিখ তৈরি করতে পারি, তবে তারিখের একটি টেবিল পেতে এবং আইডির অর্ডার দেওয়ার জন্য এটির সাথে কীভাবে যোগদান করব তা সম্পর্কে আমার কোনও ধারণা নেই। আমার কুঁচক ক্রস জয়েন কিন্তু এই পরিস্থিতিতে কীভাবে এই কাজটি করা যায় তা আমি বুঝতে পারি না।

ধন্যবাদ

আপডেট একটি বর্গক্ষেত্র ভাজা যোগ করা হয়েছে ।


2
আপনি কিছু উদাহরণ ডেটা প্রদর্শন করতে পারেন? এই সক্রিয় / অ-সক্রিয় এবং অস্থায়ী জিনিসগুলি প্রথম পড়ার পরে খুব পরিষ্কার নয়।
dezso

হ্যাঁ, এটি পরিষ্কার নয়। আপনার ক্যোয়ারী প্রতি ক্লায়েন্টের জন্য একটি আদেশ পেয়েছে এবং এটি নির্দোষ বলে মনে হচ্ছে না। যদি একই ক্লায়েন্টের সাথে ক্লায়েন্টের জন্য 2 বা ততোধিক অর্ডার থাকে তবে দু'জনের মধ্যে কোনটি প্রত্যাবর্তন করা হবে তা নির্বিচারে হবে এবং প্রতিটি মৃত্যুদন্ড কার্যকর হবে। সুতরাং, আপনি টেবিলে হয় এমন কিছু প্রতিবন্ধকতা রয়েছেন যা আপনি আমাদের বলেননি বা আপনার প্রশ্নটি সঠিক নয়।
ypercubeᵀᴹ

আমি আরও অনেক বিবরণ দিয়ে আমার প্রশ্ন আপডেট করেছি, এবং হ্যাঁ ডেটাতে সীমাবদ্ধতা রয়েছে।
পুনরায়

উত্তর:


5

আমি select distinct onউইন্ডো ফাংশন পরিবর্তে ব্যবহার করব , তারপরে কেবল দিনগুলিতে যোগ দিন।

select 
    distinct on (date, client_id) date, 
    id 
from orders
inner join generate_series('2015-07-18'::date, '2015-07-19'::date, '1 day') date
  on start_date <= date and (end_date is null or date <= end_date)
order by date, client_id, order_type desc

http://sqlfiddle.com/#!15/5a420/16/0

কিছু পরিষ্কার না হলে আমি আরও বিস্তারিত বলতে পারি।


এটি অস্থায়ী আদেশ / স্থায়ী
ক্রমটি

এটি আপনার উইন্ডো কোয়েরির মতো একই ক্রমটি নির্দিষ্ট করে। সুতরাং যে কোনও (তারিখ, ক্লায়েন্ট_আইডি) এর জন্য এটি বিপরীত বর্ণানুক্রমিক ক্রমে প্রথম অর্ডার_প্রকার নির্বাচন করবে।
সাইমন পেরেলপিলিটসা

অভ্যন্তরীণ যোগদানটি নিখুঁত, এবং সিলেক্ট পার্থক্যটি উইন্ডোটির চেয়ে বোঝা অনেক সহজ (এবং ঠিক তেমনভাবে সঞ্চালিত হয়)। অন্য কোন কারণে আমার উইন্ডোটিং ফাংশন ব্যবহার করা উচিত নয়?
পুনরায় সংযোগ করুন

1
এটা সম্বন্ধে. আমি মনে করি distinct onউইন্ডো কোয়েরির চেয়েও আরও অনুকূলিত। প্রসঙ্গক্রমে, আমি উল্লেখ করা উচিত যে এই একটি সাধারণ "শীর্ষ-ইন-গ্রুপ" SQL এর যে সমস্যা হল: stackoverflow.com/questions/3800551/...
সাইমন Perepelitsa

এটি দুর্দান্ত পড়া, আমার কিছু করণীয় আছে। আপনার যদি কিছু সময় থাকে তবে আমার কাছে এই প্রশ্নের একটি বর্ধিত সংস্করণ রয়েছে যা আমি এখানে যা শিখেছি তা ব্যবহার করে। dba.stackexchange.com/questions/108767/… আমি নিশ্চিত যে আমি এই লিঙ্কটি থেকে যা শিখেছি তা আপডেট করে ফিরে আসব। এবং ধন্যবাদ
পুনরায় সংযোগ করুন

0

এমন একটি ফাংশন লিখুন যা প্যারামিটার হিসাবে একক তারিখ নেয় এবং আদেশের সাথে তারিখের + আইডির একটি তালিকা প্রদান করে।

তারপরে, আপনার পরামর্শ অনুযায়ী জেনারেট_সরিজগুলি ব্যবহার করুন এবং ফাংশনটিকে তারিখের সীমাতে কল করুন।

এসকিউএল জটিল অবস্থার সাথে কাজ করার সময় এটি একটি সাধারণ কৌশল।

আমি নীচে কিছু কোড অন্তর্ভুক্ত করেছি, তবে উপরের এসকিউএল উত্তরটি অনেক সহজ।

ফাংশনটি এখানে:

create or replace function o( date) returns setof INT AS '
SELECT id from (
 SELECT
  id,
  first_value(id) OVER (PARTITION BY client_id ORDER BY order_type DESC) active_order_id
 FROM orders
 WHERE start_date <= $1 and (end_date is null OR end_date >= $1)
) active_orders
WHERE id = active_order_id;
' LANGUAGE sql ;

এবং কীভাবে এটি কল করবেন:

select distinct d, o(d::date) 
from generate_series('2015-07-18'::date, '2015-07-19'::date, '1 day') as d;

SQLFiddle


2
আপনি সেই উত্তরটি কিছু বিশদ, নমুনা কোড ইত্যাদির সাথে সরিয়ে ফেলতে চাইতে পারেন এটি যেমন অস্পষ্ট তাই এই উত্তরটি মুছে ফেলা হতে পারে।
ম্যাক্স ভার্নন 21

আপনি একটি উদাহরণ দিয়ে আমার ফিডল আপডেট করতে সক্ষম হবেন? sqlfiddle.com/#!15/5a420/3/0
পুনর্নবীকরণ

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