PostgreSQL - उस पंक्ति को लाएं जिसमें स्तंभ के लिए अधिकतम मान हो


96

मैं एक पोस्टग्रैज टेबल (जिसे "जीवन" कहा जाता है) के साथ काम कर रहा हूं, जिसमें time_stamp, usr_id, transaction_id, और life_remaining के कॉलम शामिल हैं। मुझे एक क्वेरी की आवश्यकता है जो मुझे प्रत्येक usr_id के लिए सबसे हालिया जीवन_प्रमाण प्रदान करेगी

  1. कई उपयोगकर्ता हैं (अलग usr_id के)
  2. टाइम_स्टैम्प एक विशिष्ट पहचानकर्ता नहीं है: कभी-कभी उपयोगकर्ता घटनाएँ (तालिका में पंक्ति द्वारा) एक ही टाइम_स्टैम्प के साथ घटित होंगी।
  3. trans_id केवल बहुत छोटी समय सीमाओं के लिए अद्वितीय है: समय के साथ यह दोहराता है
  4. शेष_लाइव (किसी दिए गए उपयोगकर्ता के लिए) समय के साथ बढ़ और घट सकता है

उदाहरण:

TIME_STAMP | lives_remaining | usr_id | trans_id
-----------------------------------------
  07:00 | 1 | 1 | 1    
  09:00 | 4 | 2 | 2    
  10:00 | 2 | 3 | 3    
  10:00 | 1 | 2 | 4    
  11:00 | 4 | 1 | 5    
  11:00 | 3 | 1 | 6    
  13:00 | 3 | 3 | 1    

जैसा कि मुझे प्रत्येक दिए गए usr_id के लिए नवीनतम डेटा के साथ पंक्ति के अन्य स्तंभों तक पहुंचने की आवश्यकता होगी, मुझे एक क्वेरी की आवश्यकता है जो इसके लिए एक परिणाम प्रदान करती है:

TIME_STAMP | lives_remaining | usr_id | trans_id
-----------------------------------------
  11:00 | 3 | 1 | 6    
  10:00 | 1 | 2 | 4    
  13:00 | 3 | 3 | 1    

जैसा कि उल्लेख किया गया है, प्रत्येक usr_id जीवन प्राप्त कर सकता है या खो सकता है, और कभी-कभी ये टाइमस्टैम्पेड घटनाएं एक साथ इतने करीब होती हैं कि उनके समान टाइमस्टैम्प होता है! इसलिए यह क्वेरी काम नहीं करेगी:

SELECT b.time_stamp,b.lives_remaining,b.usr_id,b.trans_id FROM 
      (SELECT usr_id, max(time_stamp) AS max_timestamp 
       FROM lives GROUP BY usr_id ORDER BY usr_id) a 
JOIN lives b ON a.max_timestamp = b.time_stamp

इसके बजाय, मुझे सही पंक्ति की पहचान करने के लिए time_stamp (पहला) और trans_id (दूसरा) दोनों का उपयोग करना होगा। फिर मुझे उस जानकारी को उपकुंजियों से मुख्य क्वेरी तक पारित करने की आवश्यकता है जो उचित पंक्तियों के अन्य स्तंभों के लिए डेटा प्रदान करेगी। यह हैक की गई क्वेरी है जो मुझे काम करने के लिए मिली है:

SELECT b.time_stamp,b.lives_remaining,b.usr_id,b.trans_id FROM 
      (SELECT usr_id, max(time_stamp || '*' || trans_id) 
       AS max_timestamp_transid
       FROM lives GROUP BY usr_id ORDER BY usr_id) a 
JOIN lives b ON a.max_timestamp_transid = b.time_stamp || '*' || b.trans_id 
ORDER BY b.usr_id

ठीक है, तो यह काम करता है, लेकिन मुझे यह पसंद नहीं है। इसके लिए एक क्वेरी के भीतर एक क्वेरी, एक सेल्फ जॉइन की आवश्यकता होती है, और मुझे लगता है कि यह उस पंक्ति को हथियाने से बहुत सरल हो सकता है जिसे MAX ने सबसे बड़ा टाइमस्टैम्प और ट्रांस_ड पाया। तालिका "जीवन" में पार्स करने के लिए लाखों पंक्तियाँ हैं, इसलिए मैं चाहूंगा कि यह क्वेरी यथासंभव तेज़ और कुशल हो। मैं विशेष रूप से RDBM और Postgres में नया हूं, इसलिए मुझे पता है कि मुझे उचित अनुक्रमित का प्रभावी उपयोग करने की आवश्यकता है। मैं अनुकूलित करने के तरीके पर थोड़ा खो गया हूं।

मुझे यहां इसी तरह की चर्चा मिली । क्या मैं ओरेकल एनालिटिकल फंक्शन के समकक्ष कुछ प्रकार के पोस्टग्रेज कर सकता हूं?

एक समग्र कार्य (जैसे MAX) द्वारा उपयोग किए जाने वाले संबंधित कॉलम की जानकारी तक पहुँचने पर कोई सलाह, इंडेक्स बनाने और बेहतर प्रश्न बनाने के लिए बहुत सराहना की जाएगी!

PS आप मेरे उदाहरण के मामले को बनाने के लिए निम्नलिखित का उपयोग कर सकते हैं:

create TABLE lives (time_stamp timestamp, lives_remaining integer, 
                    usr_id integer, trans_id integer);
insert into lives values ('2000-01-01 07:00', 1, 1, 1);
insert into lives values ('2000-01-01 09:00', 4, 2, 2);
insert into lives values ('2000-01-01 10:00', 2, 3, 3);
insert into lives values ('2000-01-01 10:00', 1, 2, 4);
insert into lives values ('2000-01-01 11:00', 4, 1, 5);
insert into lives values ('2000-01-01 11:00', 3, 1, 6);
insert into lives values ('2000-01-01 13:00', 3, 3, 1);

जोश, आप इस तथ्य को पसंद नहीं कर सकते हैं कि क्वेरी आत्म-जोड़ आदि, लेकिन यह ठीक है जहां तक ​​आरडीबीएमएस का संबंध है।
vladr

1
सेल्फ-ज्वाइन वास्तव में अनुवाद करने के लिए समाप्त हो जाएगा, एक साधारण इंडेक्स मैपिंग है, जहां इनर सेलेक्ट (मैक्स के साथ एक) अप्रासंगिक प्रविष्टियों को दूर करने वाले इंडेक्स को स्कैन करता है, और जहां बाहरी चयन सिर्फ टेबल से बाकी कॉलमों को पकड़ता है संकुचित-नीचे सूचकांक के अनुरूप।
vladr

व्लाद, सुझावों और स्पष्टीकरण के लिए धन्यवाद। यह मेरी आँखें खोली है कि डेटाबेस के आंतरिक कामकाज को कैसे समझना शुरू किया जाए और कैसे प्रश्नों का अनुकूलन किया जाए। क्वासोई, महान क्वेरी के लिए धन्यवाद और प्राथमिक कुंजी पर टिप; बिल भी। बहुत मददगार।
जोशुआ बेरी

मुझे दिखाने के लिए धन्यवाद कि कैसे MAX BY2 कॉलम प्राप्त करें !

जवाबों:


90

158k छद्म यादृच्छिक पंक्तियों वाली एक मेज पर (usr_id समान रूप से 0 और 10k के trans_idबीच वितरित , समान रूप से 0 और 30 के बीच वितरित),

नीचे क्वेरी मूल्य के आधार पर, मैं पोस्टग्रेज की लागत आधारित ऑप्टिमाइज़र की लागत का अनुमान (पोस्टग्रेज़ के डिफ़ॉल्ट xxx_costमानों के साथ) का उल्लेख कर रहा हूं , जो आवश्यक I / O और CPU संसाधनों का एक तौला हुआ फ़ंक्शन अनुमान है; आप PgAdminIII को फायर करके और क्वेरी का "विश्लेषण / स्पष्टीकरण विकल्प" सेट पर "क्वेरी / स्पष्टीकरण (F7)" चलाकर "विश्लेषण" करने के लिए इसे प्राप्त कर सकते हैं

  • Quassnoy की क्वेरी 1.3 सेकंड में 745k की लागत का अनुमान है (!), और कम्प्लिट्स है (पर एक यौगिक सूचकांक दी ( usr_id, trans_id, time_stamp))
  • बिल की क्वेरी की लागत का अनुमान 93k है, और 2.9 सेकंड में पूरा होता है (पर (एक कंपाउंड इंडेक्स पर ) usr_id, trans_id)
  • क्वेरी # 1 नीचे 16k की लागत का अनुमान है, और 800ms में पूर्ण होती है (पर एक यौगिक सूचकांक दी ( usr_id, trans_id, time_stamp))
  • क्वेरी # 2 नीचे 14k की लागत का अनुमान है, और 800ms में पूर्ण होती है (दिए गए पर एक यौगिक समारोह सूचकांक ( usr_id, EXTRACT(EPOCH FROM time_stamp), trans_id))
    • यह पोस्टग्रेज-स्पेसिफिक है
  • क्वेरी # 3 नीचे (Postgres 8.4+) एक लागत अनुमान और पूरा समय (या की तुलना में बेहतर) के लिए तुलनीय क्वेरी # 2 है (दिए गए पर (एक यौगिक सूचकांक usr_id, time_stamp, trans_id)); यह livesतालिका को केवल एक बार स्कैन करने का लाभ है और, क्या आपको मेमोरी में सॉर्ट को समायोजित करने के लिए अस्थायी रूप से (यदि आवश्यक हो) वर्क_मम को बढ़ाना चाहिए , तो यह सभी प्रश्नों का सबसे तेज़ होगा।

उपरोक्त सभी समय में पूर्ण 10k पंक्तियों के परिणाम-सेट की पुनः प्राप्ति शामिल है।

अनुमानित लागत पर जोर देने के साथ आपका लक्ष्य न्यूनतम लागत अनुमान और न्यूनतम क्वेरी निष्पादन समय है। क्वेरी निष्पादन रनटाइम स्थितियों पर महत्वपूर्ण रूप से निर्भर कर सकता है (जैसे कि प्रासंगिक पंक्तियों को पहले से ही पूरी तरह से मेमोरी में कैश किया गया है या नहीं), जबकि लागत का अनुमान नहीं है। दूसरी ओर, ध्यान रखें कि लागत अनुमान वास्तव में एक अनुमान है।

सबसे अच्छा क्वेरी निष्पादन समय लोड के बिना एक समर्पित डेटाबेस पर चलने पर प्राप्त किया जाता है (जैसे एक विकास पीसी पर pgAdminIII के साथ खेलना।) क्वेरी समय वास्तविक मशीन लोड / डेटा एक्सेस प्रसार के आधार पर उत्पादन में भिन्न होगा। जब एक क्वेरी दूसरे की तुलना में थोड़ी तेज (<20%) दिखाई देती है, लेकिन इसकी लागत बहुत अधिक होती है, तो आमतौर पर उच्च निष्पादन समय लेकिन कम लागत वाले को चुनना समझदारी होगी।

जब आप यह उम्मीद करते हैं कि जिस समय क्वेरी चल रही है उस समय आपकी उत्पादन मशीन पर मेमोरी के लिए कोई प्रतिस्पर्धा नहीं होगी (जैसे RDBMS कैश और फाइल सिस्टम कैश समवर्ती प्रश्नों और / या फाइलसिस्टम गतिविधि द्वारा नहीं तोड़ा जाएगा) तो क्वेरी समय आपने प्राप्त किया स्टैंडअलोन में (उदाहरण के लिए एक विकास पीसी पर pgAdminIII) ​​मोड प्रतिनिधि होगा। यदि उत्पादन प्रणाली पर विवाद है, तो क्वेरी का समय अनुमानित लागत अनुपात के अनुपात में कम हो जाएगा, क्योंकि कम लागत वाली क्वेरी कैश पर ज्यादा निर्भर नहीं करती है, जबकि उच्च लागत के साथ क्वेरी एक ही डेटा पर और फिर से शुरू हो जाएगी (ट्रिगर करना अतिरिक्त I / O एक स्थिर कैश की अनुपस्थिति में), उदाहरण के लिए:

              cost | time (dedicated machine) |     time (under load) |
-------------------+--------------------------+-----------------------+
some query A:   5k | (all data cached)  900ms | (less i/o)     1000ms |
some query B:  50k | (all data cached)  900ms | (lots of i/o) 10000ms |

ANALYZE livesआवश्यक सूचकांक बनाने के बाद एक बार दौड़ना न भूलें ।


क्वेरी # 1

-- incrementally narrow down the result set via inner joins
--  the CBO may elect to perform one full index scan combined
--  with cascading index lookups, or as hash aggregates terminated
--  by one nested index lookup into lives - on my machine
--  the latter query plan was selected given my memory settings and
--  histogram
SELECT
  l1.*
 FROM
  lives AS l1
 INNER JOIN (
    SELECT
      usr_id,
      MAX(time_stamp) AS time_stamp_max
     FROM
      lives
     GROUP BY
      usr_id
  ) AS l2
 ON
  l1.usr_id     = l2.usr_id AND
  l1.time_stamp = l2.time_stamp_max
 INNER JOIN (
    SELECT
      usr_id,
      time_stamp,
      MAX(trans_id) AS trans_max
     FROM
      lives
     GROUP BY
      usr_id, time_stamp
  ) AS l3
 ON
  l1.usr_id     = l3.usr_id AND
  l1.time_stamp = l3.time_stamp AND
  l1.trans_id   = l3.trans_max

क्वेरी # 2

-- cheat to obtain a max of the (time_stamp, trans_id) tuple in one pass
-- this results in a single table scan and one nested index lookup into lives,
--  by far the least I/O intensive operation even in case of great scarcity
--  of memory (least reliant on cache for the best performance)
SELECT
  l1.*
 FROM
  lives AS l1
 INNER JOIN (
   SELECT
     usr_id,
     MAX(ARRAY[EXTRACT(EPOCH FROM time_stamp),trans_id])
       AS compound_time_stamp
    FROM
     lives
    GROUP BY
     usr_id
  ) AS l2
ON
  l1.usr_id = l2.usr_id AND
  EXTRACT(EPOCH FROM l1.time_stamp) = l2.compound_time_stamp[1] AND
  l1.trans_id = l2.compound_time_stamp[2]

2013/01/29 अपडेट

अंत में, संस्करण 8.4 के रूप में, Postgres विंडो फ़ंक्शन का समर्थन करता है जिसका अर्थ है कि आप कुछ सरल और कुशल लिख सकते हैं:

क्वेरी # 3

-- use Window Functions
-- performs a SINGLE scan of the table
SELECT DISTINCT ON (usr_id)
  last_value(time_stamp) OVER wnd,
  last_value(lives_remaining) OVER wnd,
  usr_id,
  last_value(trans_id) OVER wnd
 FROM lives
 WINDOW wnd AS (
   PARTITION BY usr_id ORDER BY time_stamp, trans_id
   ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
 );

(Usr_id, trans_id, times_tamp) पर एक कंपाउंड इंडेक्स द्वारा, क्या आपका मतलब कुछ इस तरह है कि "CREATE INDEX रहता है_blah_idx ऑन लाइफ (usr_id, trans_id, time_stamp)"? या क्या मुझे प्रत्येक कॉलम के लिए तीन अलग-अलग इंडेक्स बनाने चाहिए? मुझे "यूएसटी बीट्री" के डिफ़ॉल्ट के साथ रहना चाहिए, है ना?
जोशुआ बेरी

1
पहली पसंद के लिए हाँ: मेरा मतलब है कि INDEX CREEX__ (जीवन के अंत तक), हमारे जीवन को बनाए रखें। :) चीयर्स।
vladr 19

यहां तक ​​कि लागत तुलना vladr करने के लिए धन्यवाद! बहुत पूरा जवाब!
एडम

@vladr मैं अभी आपके उत्तर पर आया हूं। मैं थोड़ा भ्रमित हूं, क्योंकि आप कहते हैं कि क्वेरी 1 की लागत 16k है और क्वेरी 2 की लागत 14k है। लेकिन आगे तालिका में आप कहते हैं कि क्वेरी 1 की लागत 5k है और क्वेरी 2 की लागत 50k है। तो कौन सी क्वेरी का उपयोग करने के लिए एक पसंदीदा है? :) धन्यवाद
हुमैन

1
@Kave, तालिका उदाहरणों का वर्णन करने के लिए प्रश्नों की एक काल्पनिक जोड़ी के लिए है, ओपी के दो प्रश्नों को नहीं। भ्रम को कम करने के लिए नामकरण।
vladr

77

मैं एक स्वच्छ संस्करण पर आधारित प्रस्ताव DISTINCT ON( डॉक्स देखें ):

SELECT DISTINCT ON (usr_id)
    time_stamp,
    lives_remaining,
    usr_id,
    trans_id
FROM lives
ORDER BY usr_id, time_stamp DESC, trans_id DESC;

6
यह बहुत कम और ध्वनि उत्तर है। एक अच्छा संदर्भ भी है! यह स्वीकृत उत्तर होना चाहिए।
प्रखर अग्रवाल

यह मेरे लिए मेरे अलग आवेदन पर काम करने के लिए लग रहा था, जहां और कुछ नहीं होगा। निश्चित रूप से अधिक दृश्यता के लिए उठाया जाना चाहिए।
जिम फैक्टर

8

यहाँ एक और तरीका है, जो कोई सहसंबद्ध उपश्रेणी या ग्रुप बाय का उपयोग करने के लिए होता है। मैं PostgreSQL प्रदर्शन ट्यूनिंग में विशेषज्ञ नहीं हूं, इसलिए मेरा सुझाव है कि आप यह और अन्य लोगों द्वारा दिए गए समाधानों को देखने के लिए प्रयास करें जो आपके लिए बेहतर काम करता है।

SELECT l1.*
FROM lives l1 LEFT OUTER JOIN lives l2
  ON (l1.usr_id = l2.usr_id AND (l1.time_stamp < l2.time_stamp 
   OR (l1.time_stamp = l2.time_stamp AND l1.trans_id < l2.trans_id)))
WHERE l2.usr_id IS NULL
ORDER BY l1.usr_id;

मैं मान रहा हूँ कि trans_idकिसी भी मूल्य पर कम से कम अद्वितीय है time_stamp


4

मुझे आपके द्वारा उल्लिखित दूसरे पृष्ठ पर माइक वुडहाउस के उत्तर की शैली पसंद है । यह विशेष रूप से संक्षिप्त है जब बात केवल एक स्तंभ पर अधिकतम हो रही है, जिस स्थिति में उपकुंजी बस MAX(some_col)और GROUP BYअन्य स्तंभों का उपयोग कर सकती है , लेकिन आपके मामले में आपके पास अधिकतम करने के लिए 2-भाग की मात्रा है, तो आप अभी भी इसका उपयोग कर सकते हैं ORDER BYप्लस LIMIT 1के बजाय (के रूप में Quassnoi द्वारा किया जाता):

SELECT * 
FROM lives outer
WHERE (usr_id, time_stamp, trans_id) IN (
    SELECT usr_id, time_stamp, trans_id
    FROM lives sq
    WHERE sq.usr_id = outer.usr_id
    ORDER BY trans_id, time_stamp
    LIMIT 1
)

मुझे पंक्ति-कंस्ट्रक्टर सिंटैक्स का उपयोग करना WHERE (a, b, c) IN (subquery)अच्छा लगता है क्योंकि यह आवश्यक मात्रा में कटौती करता है।


3

Actaully इस समस्या के लिए एक घिनौना समाधान है। मान लीजिए कि आप एक क्षेत्र में प्रत्येक जंगल के सबसे बड़े पेड़ का चयन करना चाहते हैं।

SELECT (array_agg(tree.id ORDER BY tree_size.size)))[1]
FROM tree JOIN forest ON (tree.forest = forest.id)
GROUP BY forest.id

जब आप जंगलों द्वारा पेड़ों का समूह बनाते हैं, तो पेड़ों की एक अनसुलझी सूची होगी और आपको सबसे बड़ी खोज करनी होगी। पहली बात यह है कि आपको पंक्तियों को उनके आकारों के आधार पर क्रमबद्ध करना होगा और अपनी सूची में से पहले का चयन करना होगा। यह अक्षम लग सकता है, लेकिन अगर आपके पास लाखों पंक्तियां हैं, तो यह उन समाधानों की तुलना में काफी तेज होगा, जिनमें स्थितियां JOINऔर WHEREशर्तें शामिल हैं।

Btw, ध्यान दें कि ORDER_BYके लिए array_aggPostgresql 9.0 में शुरू की है


आपके पास एक त्रुटि है। आपको ORDER BY tree_size.size DESC लिखना होगा। इसके अलावा, लेखक के कार्य के लिए कोड इस तरह दिखाई देगा: SELECT usr_id, (array_agg(time_stamp ORDER BY time_stamp DESC))[1] AS timestamp, (array_agg(lives_remaining ORDER BY time_stamp DESC))[1] AS lives_remaining, (array_agg(trans_id ORDER BY time_stamp DESC))[1] AS trans_id FROM lives GROUP BY usr_id
alexkovelsky

2

Postgressql 9.5 में एक नया विकल्प है जिसे DISTINCT ON कहा जाता है

SELECT DISTINCT ON (location) location, time, report
    FROM weather_reports
    ORDER BY location, time DESC;

यह डुप्लिकेट पंक्तियों को केवल एक पहली पंक्ति के रूप में समाप्त करता है जैसा कि मेरे आदेश द्वारा खंड को परिभाषित किया गया है।

आधिकारिक दस्तावेज देखें


1
SELECT  l.*
FROM    (
        SELECT DISTINCT usr_id
        FROM   lives
        ) lo, lives l
WHERE   l.ctid = (
        SELECT ctid
        FROM   lives li
        WHERE  li.usr_id = lo.usr_id
        ORDER BY
          time_stamp DESC, trans_id DESC
        LIMIT 1
        )

एक इंडेक्स (usr_id, time_stamp, trans_id)बनाने से इस क्वेरी में बहुत सुधार होगा।

आपको हमेशा, PRIMARY KEYअपनी तालिकाओं में किसी प्रकार का होना चाहिए ।


0

मुझे लगता है कि आपको यहां एक बड़ी समस्या मिल गई है: यह गारंटी देने के लिए कि कोई दी गई पंक्ति किसी अन्य की तुलना में बाद में हुई है, कोई नीरसता से "काउंटर" नहीं बढ़ रही है। इस उदाहरण को लें:

timestamp   lives_remaining   user_id   trans_id
10:00       4                 3         5
10:00       5                 3         6
10:00       3                 3         1
10:00       2                 3         2

आप इस डेटा से निर्धारित नहीं कर सकते हैं जो कि सबसे हाल की प्रविष्टि है। क्या यह दूसरा है या आखिरी है? कोई भी प्रकार या अधिकतम () फ़ंक्शन नहीं है जो आपको सही उत्तर देने के लिए इस डेटा में से किसी पर भी लागू हो सकता है।

टाइमस्टैम्प के संकल्प को बढ़ाना एक बड़ी मदद होगी। चूंकि डेटाबेस इंजन अनुरोधों को क्रमबद्ध करता है, इसलिए पर्याप्त रिज़ॉल्यूशन के साथ आप गारंटी दे सकते हैं कि कोई भी दो टाइमस्टैम्प समान नहीं होंगे।

वैकल्पिक रूप से, एक ट्रांस_ड का उपयोग करें जो बहुत लंबे समय तक रोल नहीं करेगा। Trans_id होने पर इसका मतलब है कि आप (उसी टाइमस्टैम्प के लिए) बता नहीं सकते हैं कि क्या trans_id 6 trans_id 1 से अधिक हाल का है जब तक कि आप कुछ जटिल गणित नहीं करते।


हां, आदर्श रूप से एक क्रम (ऑटोनक्राइमेंट) कॉलम क्रम में होगा।
vladr

ऊपर से धारणा यह थी कि छोटे समय के वेतन वृद्धि के लिए, ट्रांस_ड रोल नहीं होगा। मैं मानता हूं कि तालिका को एक अद्वितीय प्राथमिक सूचकांक की आवश्यकता है - एक गैर-दोहराए जाने वाले ट्रांस_ड की तरह। (PS मुझे खुशी है कि मेरे पास अब टिप्पणी करने के लिए पर्याप्त कर्म / प्रतिष्ठा अंक हैं!)
जोशुआ बेरी

व्लाद का कहना है कि ट्रांस_ड में एक छोटा चक्र है जो अक्सर बदल जाता है। यहां तक ​​कि अगर आप मेरी मेज से केवल दो मध्य पंक्तियों (ट्रांस_ड = 6 और 1) पर विचार करते हैं, तो भी आप यह नहीं बता सकते कि हाल ही में कौन सा है। इसलिए, किसी दिए गए टाइमस्टैम्प के लिए अधिकतम (ट्रांस_ड) का उपयोग करना काम नहीं करेगा।
बैरी ब्राउन

हां, मैं एप्लिकेशन लेखक की गारंटी पर भरोसा कर रहा हूं कि किसी दिए गए उपयोगकर्ता के लिए (time_stamp, trans_id) ट्यूपल अद्वितीय है। अगर ऐसा नहीं है तो "SELECT l1.usr_id, l1.lives_left, ... FROM ... WHERE ..." को "SELECT l1.usr_id, MAX / MIN (l1.lives_left), ... FROM बनना चाहिए।" .. जहां ... ग्रुप बाय l1.usr_id, ...
vladr 19

0

एक और उपाय जो आपको उपयोगी लग सकता है।

SELECT t.*
FROM
    (SELECT
        *,
        ROW_NUMBER() OVER(PARTITION BY usr_id ORDER BY time_stamp DESC) as r
    FROM lives) as t
WHERE t.r = 1
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.