PostgreSQL - একটি কলামের সর্বাধিক মান রয়েছে এমন সারিটি আনুন fet


99

আমি পোস্টগ্রিস টেবিলের সাথে কাজ করছি (যাকে "লাইভ" বলা হয়) এতে টাইম_স্ট্যাম্প, ইউএসআরআইডি, লেনদেন_আইড, এবং লাইফসাইডিংয়ের জন্য কলাম সহ রেকর্ড রয়েছে। আমার কাছে এমন একটি কোয়েরি দরকার যা প্রতিটি usr_id এর জন্য আমাকে সর্বশেষতম জীবন_সামরণ দেবে

  1. একাধিক ব্যবহারকারী রয়েছে (স্বতন্ত্র ইউএস_আইডি)
  2. টাইম_স্ট্যাম্প কোনও অনন্য শনাক্তকারী নয়: কখনও কখনও ব্যবহারকারীর ইভেন্টগুলি (টেবিলের এক এক সারি) একই সময়_স্ট্যাম্পের সাথে ঘটে।
  3. trans_id কেবলমাত্র খুব অল্প সময়ের জন্যই অনন্য: সময়ের সাথে সাথে এটি পুনরাবৃত্তি করে
  4. অবশিষ্ট_লাইভগুলি (প্রদত্ত ব্যবহারকারীর জন্য) সময়ের সাথে সাথে উভয়ই বৃদ্ধি বা হ্রাস করতে পারে

উদাহরণ:

সময়_স্ট্যাম্প | জীবন_সামরণ | usr_id | ট্রান্সআইড _
-----------------------------------------
  07:00 | 1 | 1 | ঘ    
  09:00 | 4 | 2 | ঘ    
  10:00 | 2 | 3 | ঘ    
  10:00 | 1 | 2 | ঘ    
  11:00 | 4 | 1 | 5    
  11:00 | 3 | 1 | ।    
  13:00 | 3 | 3 | ঘ    

যেহেতু প্রতিটি দেওয়া usr_id এর সর্বশেষতম ডেটা সহ আমার সারিটির অন্যান্য কলামগুলি অ্যাক্সেস করতে হবে, আমার একটি ক্যোয়ারী দরকার যা এর ফলাফল দেয়:

সময়_স্ট্যাম্প | জীবন_সামরণ | usr_id | ট্রান্সআইড _
-----------------------------------------
  11:00 | 3 | 1 | ।    
  10:00 | 1 | 2 | ঘ    
  13:00 | 3 | 3 | ঘ    

যেমনটি উল্লেখ করা হয়েছে, প্রতিটি 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

পরিবর্তে, সঠিক সারিটি সনাক্ত করতে আমাকে টাইমস্ট্যাম্প (প্রথম) এবং ট্রান্সআইড (দ্বিতীয়) উভয়ই ব্যবহার করতে হবে। তারপরে আমাকে সাব-কোয়েরি থেকে মূল ক্যোয়ারিতে সেই তথ্যটি পাঠাতে হবে যা উপযুক্ত সারিগুলির অন্যান্য কলামগুলির জন্য ডেটা সরবরাহ করবে। এটি হ্যাক আপ ক্যোয়ারী যা আমি কাজ করতে পেরেছি:

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

ঠিক আছে, সুতরাং এটি কাজ করে, তবে আমি এটি পছন্দ করি না। এটির জন্য একটি ক্যোয়ারির মধ্যে একটি কোয়েরি প্রয়োজন, একটি স্ব-যোগদান করুন এবং এটি আমার কাছে মনে হয় যে ম্যাক্স সর্বাধিক টাইমস্ট্যাম্প এবং ট্রান্স_আইডি পেয়েছে এমন সারিটি ধরে ফেললে এটি আরও সহজ হতে পারে। "জীবন" সারণিতে কয়েক মিলিয়ন সারি পার্স করার জন্য রয়েছে, তাই আমি চাইব যে এই ক্যোয়ারীটি যত দ্রুত সম্ভব এবং তত দ্রুত কার্যকর হোক। আমি আরডিবিএম এবং বিশেষত পোস্টগ্র্রেসে নতুন, তাই আমি জানি যে আমাকে সঠিক সূচকগুলির কার্যকর ব্যবহার করা দরকার। আমি কীভাবে অপ্টিমাইজ করব সে সম্পর্কে আমি কিছুটা হারিয়েছি।

আমি একটি অনুরূপ আলোচনা পাওয়া এখানে । আমি কি ওরাকল বিশ্লেষণমূলক ফাংশনের সমতুল্য কিছু ধরণের পোস্টগ্রিস সম্পাদন করতে পারি?

একটি সামগ্রিক ফাংশন (ম্যাক্সের মতো) দ্বারা ব্যবহৃত কলাম সম্পর্কিত তথ্য অ্যাক্সেস, সূচী তৈরি এবং আরও ভাল প্রশ্ন তৈরির বিষয়ে যে কোনও পরামর্শই প্রশংসিত হবে!

পিএস আপনি আমার উদাহরণ কেস তৈরি করতে নিম্নলিখিত ব্যবহার করতে পারেন:

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);

জোশ, আপনি যে ক্যোয়ারীটি স্ব-সাথে যোগ দেয় ইত্যাদি সত্য পছন্দ নাও করতে পারেন তবে আরডিবিএমএসের দিক থেকে এটি ঠিক আছে।
ভ্লাদ

4
স্ব-যোগদানটি আসলে যা অনুবাদ করবে তা হ'ল একটি সাধারণ সূচি ম্যাপিং, যেখানে অভ্যন্তরীণ নির্বাচন (ম্যাক্স সহ একটি) অপ্রাসঙ্গিক এন্ট্রিগুলি ছুঁড়ে ফেলে সূচকে স্ক্যান করে এবং যেখানে বাইরের SELECT কেবল সারণী থেকে বাকী কলামগুলি ধরে ফেলে সংকীর্ণ-ডাউন সূচকের সাথে সম্পর্কিত।
ভ্লাদ

ভাল, টিপস এবং ব্যাখ্যা জন্য ধন্যবাদ। এটি কীভাবে ডাটাবেসের অভ্যন্তরীণ কার্যকারিতা বুঝতে এবং কীভাবে প্রশ্নগুলি অনুকূল করতে পারে তা আমার চোখ খুলেছে। কাসনসুই, দুর্দান্ত কী এবং মূল কী সম্পর্কে পরামর্শ দেওয়ার জন্য ধন্যবাদ; বিলও। খুব উপকারী.
জোশুয়া বেরি

MAX BY2 কলাম কীভাবে পাবেন তা দেখানোর জন্য আপনাকে ধন্যবাদ !

উত্তর:


93

158 কে সিউডো-এলোমেলো সারি সহ একটি টেবিলে (usr_id 0 থেকে 10 কে trans_idমধ্যে সমানভাবে বিতরণ করা হয়েছে , 0 থেকে 30 এর মধ্যে সমানভাবে বিতরণ করা হয়েছে),

কোয়েরি ব্যয় অনুসারে, আমি পোস্টগ্র্রেসের ব্যয় ভিত্তিক অপটিমাইজারের ব্যয় প্রাক্কলন (পোস্টগ্রিসের ডিফল্ট xxx_costমান সহ) উল্লেখ করছি, যা প্রয়োজনীয় আই / ও এবং সিপিইউ সংস্থানগুলির একটি ওজনযুক্ত ফাংশন অনুমান; আপনি 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একবারে টেবিলটি স্ক্যান করার সুবিধা রয়েছে এবং, যদি মেমরির অনুসারে বাছাই করতে work_mem সাময়িকভাবে আপনার প্রয়োজন (যদি প্রয়োজন হয়) বাড়ানো উচিত তবে এটি সমস্ত প্রশ্নের মধ্যে সবচেয়ে দ্রুততম হবে।

উপরের সমস্ত সময়ে সম্পূর্ণ 10 কে সারি ফলাফল-সেট পুনরুদ্ধার অন্তর্ভুক্ত।

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

লোড ছাড়াই ডেডিকেটেড ডাটাবেসে চলাকালীন সেরা ক্যোয়ারি এক্সিকিউশন সময় পাওয়া যায় (উদাহরণস্বরূপ ডেভলপমেন্ট পিসিতে pgAdminIII সাথে খেলানো)) প্রকৃত মেশিন লোড / ডেটা অ্যাক্সেস স্প্রেডের উপর ভিত্তি করে প্রশ্নের সময় উত্পাদনে আলাদা হবে। যখন একটি ক্যোয়ারী অন্যটির তুলনায় কিছুটা দ্রুত (<20%) প্রদর্শিত হয় তবে এর দাম আরও বেশি হয়, তবে সাধারণত উচ্চতর নির্বাহের সময় তবে কম ব্যয় সহ একটি বেছে নেওয়া বুদ্ধিমানের কাজ হবে।

যখন আপনি আশা করেন যে ক্যোয়ারি চালুর সময় আপনার প্রযোজনা মেশিনে মেমরির জন্য কোনও প্রতিযোগিতা থাকবে না (উদাহরণস্বরূপ আরডিবিএমএস ক্যাশে এবং ফাইল সিস্টেম ক্যাশে সমবর্তী প্রশ্নগুলি এবং / অথবা ফাইল সিস্টেমের ক্রিয়াকলাপ দ্বারা ছিন্ন করা হবে না) তখন আপনার ক্যোয়ারির সময়টি পেয়েছে স্বতন্ত্র অবস্থায় (যেমন উন্নয়ন পিসিতে pgAdminIII) ​​মোডটি প্রতিনিধিত্ব করবেন be যদি উত্পাদন ব্যবস্থার বিষয়ে বিতর্ক থাকে তবে ক্যোয়ারির সময় আনুমানিক ব্যয় অনুপাতের সাথে আনুপাতিকভাবে হ্রাস পাবে, কারণ কম ব্যয়ের সাথে ক্যোয়ারী ক্যাশে তেমন নির্ভর করে না যখন উচ্চতর ব্যয়ের সাথে ক্যোয়ারী একই ডেটা বারবার দেখাবে (ট্রিগার) স্থিতিশীল ক্যাশের অভাবে অতিরিক্ত 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 আপডেট

পরিশেষে, সংস্করণ ৮.৪ অনুসারে, পোস্টগ্রিস উইন্ডো ফাংশন সমর্থন করে যার অর্থ আপনি সাধারণ এবং দক্ষ হিসাবে কিছু লিখতে পারেন:

প্রশ্ন # 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) - তে একটি যৌগিক সূচক দ্বারা, আপনি কি "ক্রিয়েট ইন্ডেক্স লাইভ_ব্লাহ_আইডিএক্স লাইফ (ইউএসআর_আইডি, ট্রান্স_আইডি, টাইম_স্ট্যাম্প)" এর মতো কিছু বলতে চান? বা প্রতিটি কলামের জন্য আমাকে তিনটি পৃথক সূচী তৈরি করা উচিত? আমাকে "ইউএসইং বিট্রি" এর ডিফল্ট সাথে থাকা উচিত, তাই না?
জোশুয়া বেরি

4
হ্যাঁ প্রথম পছন্দ: হ'ল আমার অর্থ ক্রিয়েট ইন্ডেক্স লাইভ_ব্লাহ_আইডিএক্স লাইভ (ইউএসআর_আইডি, ট্রান্স_আইডি, সময়_স্তম্ভ)। :) চিয়ার্স
ভ্লাদ

এমনকি ব্যয় তুলনা ভ্লাদার জন্য ধন্যবাদ! খুব সম্পূর্ণ উত্তর!
অ্যাডাম

@ ভ্লাদর আমি আপনার উত্তরটি পেরিয়ে এসেছি। আমি কিছুটা বিভ্রান্ত, আপনি যেমনটি বলেন যে ক্যোয়ারী 1 এর 16k এবং কোয়েরি 2টির 14k এর ব্যয় আছে। তবে আরও টেবিলের নিচে আপনি বলছেন যে ক্যোরি 1 এর 5k এবং কোয়েরি 2 এর দাম 50k হয়। তাহলে কোন জিজ্ঞাসাটি ব্যবহার করা পছন্দসই? :) ধন্যবাদ
হিউম্যান

4
কেভ, টেবিলটি একটি উদাহরণের জন্য অনুমানমূলক যুগল প্রশ্নের জন্য, উদাহরণস্বরূপ ওপি'র দুটি প্রশ্নের নয়। বিভ্রান্তি কমাতে নামকরণ।
ভ্লাদ

84

আমি উপর ভিত্তি করে একটি পরিষ্কার সংস্করণ প্রস্তাব করব 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

এখানে অন্য একটি পদ্ধতি রয়েছে, যা কোনও সম্পর্কযুক্ত সাবকোয়ারি বা গ্রুপ দ্বারা ব্যবহার না করে। আমি পোস্টগ্রিজএসকিউএল পারফরম্যান্স টিউনিংয়ের ক্ষেত্রে বিশেষজ্ঞ নই, তাই আমি আপনাকে পরামর্শ দিচ্ছি যে আপনার জন্য কোনটি আরও ভাল কাজ করে তা দেখার জন্য আপনি এবং অন্যান্য ভাবেনদের দেওয়া সমাধান দুটিই চেষ্টা করে দেখুন।

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পরিবর্তে (ক্যাসনোই দ্বারা সম্পন্ন হিসাবে):

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)কারণ এটি প্রয়োজনীয় পরিমাণে ভার্চিয়াটি হ্রাস করে।


4

প্রকৃতপক্ষে এই সমস্যার একটি হ্যাকি সমাধান রয়েছে। ধরা যাক আপনি কোনও অঞ্চলে প্রতিটি বনের বৃহত্তম গাছ নির্বাচন করতে চান।

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 চালু করা হয়


আপনার একটি ত্রুটি আছে। আপনার অর্ডার বাই ট্রি_সাইজ.সাইজ ডিএসসি লিখতে হবে। এছাড়াও, লেখকের 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
কাজগুলির

3

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

আপনি সর্বাধিক সাম্প্রতিক এন্ট্রিটি এই ডেটা থেকে নির্ধারণ করতে পারবেন না। এটি দ্বিতীয়টি না শেষটি? কোনও সঠিক বা সর্বোচ্চ () ফাংশন নেই আপনি সঠিক উত্তর দিতে আপনি এই ডেটার যে কোনওটিতে প্রয়োগ করতে পারেন।

টাইমস্ট্যাম্পের রেজোলিউশন বৃদ্ধি করা একটি বিশাল সহায়ক হবে। যেহেতু ডাটাবেস ইঞ্জিন অনুরোধকে সিরিয়ালাইজ করেছে, পর্যাপ্ত রেজোলিউশনের সাথে আপনি গ্যারান্টি দিতে পারবেন যে কোনও দুটি টাইমস্ট্যাম্প একই রকম হবে না।

বিকল্পভাবে, এমন একটি ট্রান্স_আইড ব্যবহার করুন যা খুব দীর্ঘ সময় ধরে চলে না। ট্রান্সআইড থাকার ফলে রোলগুলি বোঝানো হচ্ছে আপনি ট্রান্স_আইড 6 ট্রান্স_আইড 1 এর চেয়ে সাম্প্রতিক কিনা তা বলতে পারবেন না (একই টাইমস্ট্যাম্পের জন্য) আপনি যদি কিছু জটিল গণিত না করেন।


হ্যাঁ, আদর্শভাবে একটি সিকোয়েন্স (স্বতঃসংশোধন) কলামটি হবে।
ভ্লাদ্র

উপরের থেকে অনুমানটি হ'ল স্বল্প সময়ের ইনক্রিমেন্টের জন্য, ট্রান্স_আইডি গড়াবে না। আমি সম্মত হই যে টেবিলটির একটি অনন্য প্রাথমিক সূচি দরকার - একটি পুনরাবৃত্তি ট্রান্স_আইডের মতো like (পিএস আমি খুশি যে আমার এখন মন্তব্য করার মতো যথেষ্ট কর্ম / খ্যাতি পয়েন্ট রয়েছে!)
জোশুয়া বেরি

ভ্লাদ বলেছে যে ট্রান্স_আইডিটির পরিবর্তে একটি সংক্ষিপ্ত চক্র রয়েছে যা ঘন ঘন ঘন ঘন ঘন ঘন ঘন ঘন ঘন ঘন ঘন ঘন ঘন ঘন ফিরে আসে। এমনকি যদি আপনি আমার টেবিল থেকে কেবল মাঝের দুটি সারি বিবেচনা করেন (trans_id = 6 এবং 1) তবে আপনি এখনও বলতে পারবেন না কোনটি অতি সাম্প্রতিক। সুতরাং, প্রদত্ত টাইমস্ট্যাম্পের জন্য সর্বাধিক (ট্রান্স_আইডি) ব্যবহার করা কার্যকর হবে না।
ব্যারি ব্রাউন

হ্যাঁ, আমি অ্যাপ্লিকেশন লেখকের গ্যারান্টির উপর নির্ভর করছি যে প্রদত্ত ব্যবহারকারীর (টাইমস্ট্যাম্প, ট্রান্স_আইডি) টিপলটি অনন্য। যদি এটি না হয় তবে "নির্বাচন করুন l1.usr_id, l1.lives_left, ... থেকে ... যেখানে ..." অবশ্যই "নির্বাচন করুন l1.usr_id, MAX / MIN (l1.lives_left), ... থেকে হতে হবে। .. কোথায় ... l1.usr_id দ্বারা গ্রুপ, ...
ভ্লাদ

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
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.