PostgreSQL
 sql >> डेटाबेस >  >> RDS >> PostgreSQL

PostgreSQL में अतिव्यापी दिनांक सीमाएँ खोजें

वर्तमान में स्वीकृत उत्तर प्रश्न का उत्तर नहीं देता है। और यह सिद्धांत रूप में गलत है। a BETWEEN x AND y में अनुवाद करता है:

a >= x AND a <= y

सहित ऊपरी सीमा, जबकि लोगों को आमतौर पर बहिष्कृत . की आवश्यकता होती है यह:

a >= x AND a < y

तारीखों के साथ आप आसानी से समायोजित कर सकते हैं। वर्ष 2009 के लिए '2009-12-31' को ऊपरी सीमा के रूप में उपयोग करें।
लेकिन यह टाइमस्टैम्प के साथ उतना आसान नहीं है। जो भिन्नात्मक अंकों की अनुमति देता है। आधुनिक पोस्टग्रेज संस्करण आंतरिक रूप से एक 8-बाइट पूर्णांक का उपयोग 6 भिन्नात्मक सेकंड (µs रिज़ॉल्यूशन) तक संग्रहीत करने के लिए करते हैं। यह जानकर हम कर सकते थे अभी भी इसे काम करते हैं, लेकिन यह सहज नहीं है और कार्यान्वयन विवरण पर निर्भर करता है। बुरा विचार।

इसके अलावा, a BETWEEN x AND y ओवरलैपिंग रेंज नहीं ढूंढता है। हमें चाहिए:

b >= x AND a < y

और ऐसे खिलाड़ी जिन्होंने कभी नहीं छोड़ा अभी तक विचार नहीं किया गया है।

उचित उत्तर

वर्ष मानते हुए 2009 , मैं इसका अर्थ बदले बिना प्रश्न को फिर से लिखूंगा:

"किसी दी गई टीम के सभी खिलाड़ियों को खोजें जो 2010 से पहले शामिल हुए और 2009 से पहले नहीं गए।"

मूल प्रश्न:

SELECT p.*
FROM   team     t
JOIN   contract c USING (name_team) 
JOIN   player   p USING (name_player) 
WHERE  t.name_team = ? 
AND    c.date_join  <  date '2010-01-01'
AND    c.date_leave >= date '2009-01-01';

लेकिन और भी है:

यदि FK बाधाओं के साथ संदर्भात्मक अखंडता को लागू किया जाता है, तो तालिका team क्वेरी में केवल शोर है और इसे हटाया जा सकता है।

जबकि वही खिलाड़ी एक ही टीम को छोड़ सकता है और फिर से जुड़ सकता है, हमें संभावित डुप्लिकेट को भी मोड़ना होगा, उदाहरण के लिए DISTINCT के साथ ।

और हम हो सकता है एक विशेष मामले के लिए प्रदान करने की आवश्यकता है:ऐसे खिलाड़ी जिन्होंने कभी नहीं छोड़ा। मान लें कि उन खिलाड़ियों के पास date_leave . में NULL है ।

"एक खिलाड़ी जिसके बारे में पता नहीं है कि वह चला गया है, उसे आज तक टीम के लिए खेल रहा माना जाता है।"

परिष्कृत क्वेरी:

SELECT DISTINCT p.* 
FROM   contract c
JOIN   player   p USING (name_player) 
WHERE  c.name_team = ? 
AND    c.date_join  <  date '2010-01-01'
AND   (c.date_leave >= date '2009-01-01' OR c.date_leave IS NULL);

ऑपरेटर वरीयता हमारे खिलाफ काम करती है, AND OR . से पहले बाइंड करता है . हमें कोष्ठक चाहिए।

अनुकूलित के साथ संबंधित उत्तर DISTINCT (यदि डुप्लीकेट आम हैं):

  • अनेक से अनेक टेबल - प्रदर्शन खराब है

आमतौर पर, नाम प्राकृतिक व्यक्तियों की संख्या अद्वितीय नहीं है और एक सरोगेट प्राथमिक कुंजी का उपयोग किया जाता है। लेकिन, जाहिर है, name_player player . की प्राथमिक कुंजी है . अगर आपको केवल खिलाड़ियों के नाम चाहिए तो हमें टेबल की जरूरत नहीं है player क्वेरी में, या तो:

SELECT DISTINCT name_player 
FROM   contract
WHERE  name_team = ? 
AND    date_join  <  date '2010-01-01'
AND   (date_leave >= date '2009-01-01' OR date_leave IS NULL);

एसक्यूएल OVERLAPS ऑपरेटर

मैनुअल:

<ब्लॉकक्वॉट>

OVERLAPS स्वचालित रूप से जोड़ी के पहले मान को प्रारंभ के रूप में लेता है। प्रत्येक समयावधि को अर्ध-खुले अंतराल start <= time < end . का प्रतिनिधित्व करने के लिए माना जाता है , जब तक start और end बराबर हैं जिस स्थिति में यह उस एकल समय को तत्काल दर्शाता है।

संभावित NULL . का ध्यान रखने के लिए मान, COALESCE सबसे आसान लगता है:

SELECT DISTINCT name_player 
FROM   contract
WHERE  name_team = ? 
AND    (date_join, COALESCE(date_leave, CURRENT_DATE)) OVERLAPS
       (date '2009-01-01', date '2010-01-01');  -- upper bound excluded

इंडेक्स सपोर्ट के साथ रेंज टाइप

पोस्टग्रेज में 9.2 या बाद के संस्करण आप वास्तविक श्रेणी प्रकारों . के साथ भी काम कर सकते हैं :

SELECT DISTINCT name_player 
FROM   contract
WHERE  name_team = ? 
AND    daterange(date_join, date_leave) &&
       daterange '[2009-01-01,2010-01-01)';  -- upper bound excluded

रेंज प्रकार कुछ ओवरहेड जोड़ते हैं और अधिक स्थान घेरते हैं। 2 x date =8 बाइट्स; 1 एक्स daterange =डिस्क पर 14 बाइट्स या रैम में 17 बाइट्स। लेकिन ओवरलैप ऑपरेटर && . के संयोजन में क्वेरी को जीआईएसटी इंडेक्स के साथ समर्थित किया जा सकता है।

साथ ही, NULL मानों को विशेष-केस करने की कोई आवश्यकता नहीं है। NULL का अर्थ है "ओपन रेंज" एक श्रेणी प्रकार में - ठीक वही जो हमें चाहिए। तालिका परिभाषा को बदलने की भी आवश्यकता नहीं है:हम मक्खी पर श्रेणी प्रकार बना सकते हैं - और मिलान अभिव्यक्ति सूचकांक के साथ क्वेरी का समर्थन कर सकते हैं:

CREATE INDEX mv_stock_dr_idx ON mv_stock USING gist (daterange(date_join, date_leave));

संबंधित:

  • औसत स्टॉक इतिहास तालिका


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. अभिव्यक्ति सूचकांकों की उपयोगिता पर

  2. मैं PostgreSQL 9.5 में एक int डेटाटाइप के लिए आकार सीमा कैसे निर्धारित कर सकता हूं?

  3. psql के साथ त्रुटियों को कैसे अनदेखा करें \ कॉपी मेटा-कमांड

  4. लोअर लाइक बनाम आईलाइक

  5. रूबी 'पीजी' मणि libpq.5.dylib (OSX पर) की गलत प्रति से जुड़ती है