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


574

টেবিল:

UserId, Value, Date.

আমি প্রতিটি ইউজারআইডি-র সর্বোচ্চ (তারিখ) এর মান ইউজারআইডি পেতে চাই। এটি হ'ল প্রতিটি ইউজারআইডির মান যার সর্বশেষতম তারিখ রয়েছে। এসকিউএল এ সহজভাবে করার উপায় আছে? (সাধারণত ওরাকল)

আপডেট: যে কোনও অস্পষ্টতার জন্য ক্ষমা চাইছি: আমার সমস্ত ইউজারআইডস নেওয়া দরকার। তবে প্রতিটি ইউজারআইডির জন্য কেবল সেই সারি যেখানে সেই ব্যবহারকারীর সর্বশেষ তারিখ রয়েছে।


21
যদি একাধিক সারি একটি নির্দিষ্ট ইউজারিডের সর্বাধিক তারিখের মান থাকে?
ডেভিড অলড্রিজ

টেবিলের মূল ক্ষেত্রগুলি কী কী?
বামোসরাফ

নিচে তুলনায় কিছু সমাধান: sqlfiddle.com/#!4/6d4e81/1
Used_By_Already

1
@ ডেভিডএলড্রিজ, এই কলামটি সম্ভবত অনন্য।
পেসারিয়ার

উত্তর:


397

এটি সেই সমস্ত সারি পুনরুদ্ধার করবে যার জন্য my_date কলামের মানটি সেই ইউজারিডের সর্বাধিক মানের my_date এর সমান। এটি ইউজারিডের জন্য একাধিক সারি পুনরুদ্ধার করতে পারে যেখানে সর্বাধিক তারিখটি একাধিক সারিতে থাকে।

select userid,
       my_date,
       ...
from
(
select userid,
       my_date,
       ...
       max(my_date) over (partition by userid) max_my_date
from   users
)
where my_date = max_my_date

"বিশ্লেষণমূলক ফাংশন রক"

সম্পাদনা: প্রথম মন্তব্য সম্পর্কিত ...

"বিশ্লেষণমূলক ক্যোয়ারী ব্যবহার করে এবং একটি স্ব-যোগদান যোগদান বিশ্লেষণমূলক প্রশ্নের উদ্দেশ্যকে পরাস্ত করে"

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

"ওরাকল-এ ডিফল্ট উইন্ডোটি পার্টিশনের প্রথম সারি থেকে বর্তমানের একটিতে"

উইন্ডোটিং ক্লজটি কেবল ধারা দ্বারা আদেশের উপস্থিতিতে প্রযোজ্য। ধারা দ্বারা কোনও আদেশ ছাড়াই, কোনও উইন্ডোনিং ধারাটি ডিফল্টরূপে প্রয়োগ হয় না এবং কোনওটিই স্পষ্টভাবে নির্দিষ্ট করা যায় না।

কোড কাজ করে।


38
৮.৮ মিলিয়ন সারি থাকা কোনও টেবিলে প্রয়োগ করা হলে, এই কোয়েরিতে বেশ কয়েকটি অন্যান্য অত্যন্ত ভোট দেওয়া উত্তরের প্রশ্নের প্রায় অর্ধেক সময় নিয়েছিল।
ডেরেক মাহর

4
যে কেউ এর মাইএসকিউএল সমতুল্য একটি লিঙ্ক পোস্ট করার জন্য যত্নশীল, যদি সেখানে থাকে?
স্মৃতিভারাতুর

2
এই ফিরতি সদৃশ না? যেমন। যদি দুটি সারিতে একই ব্যবহারকারী_আইড এবং একই তারিখ থাকে (যা সর্বাধিক হতে পারে)।
জাস্টার

2
@ জাস্টার আমি মনে করি যে প্রশ্নটিতে তা স্বীকৃত হয়েছিল
ডেভিড অলড্রিজ

3
পরিবর্তে MAX(...) OVER (...)আপনি ROW_NUMBER() OVER (...)(শীর্ষ-এন-প্রতি-গ্রুপের জন্য) বা RANK() OVER (...)(সেরা-এন-প্রতি-গ্রুপের জন্য )ও ব্যবহার করতে পারেন।
এমটি0

441

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

SELECT t1.*
FROM mytable t1
  LEFT OUTER JOIN mytable t2
    ON (t1.UserId = t2.UserId AND t1."Date" < t2."Date")
WHERE t2.UserId IS NULL;

অন্য কথায়: যে সারিটি t1একই UserIdএবং বৃহত্তর তারিখের সাথে উপস্থিত নেই সেখান থেকে সারিটি আনুন ।

(আমি সনাক্তকারী "তারিখ" প্রেরকগুলিতে রেখেছি কারণ এটি একটি এসকিউএল সংরক্ষিত শব্দ))

ক্ষেত্রে যদি t1."Date" = t2."Date", দ্বিগুণ উপস্থিত হয়। সাধারণত টেবিলগুলির auto_inc(seq)কী থাকে, যেমন id। দ্বিগুণ এড়াতে নিম্নলিখিত ব্যবহার করা যেতে পারে:

SELECT t1.*
FROM mytable t1
  LEFT OUTER JOIN mytable t2
    ON t1.UserId = t2.UserId AND ((t1."Date" < t2."Date") 
         OR (t1."Date" = t2."Date" AND t1.id < t2.id))
WHERE t2.UserId IS NULL;

@ ফারহানের মন্তব্য:

এখানে আরও বিস্তারিত ব্যাখ্যা দেওয়া হয়েছে:

একটি বহিরাগত যোগদানের t1সাথে যোগদানের চেষ্টা করে t2। ডিফল্টরূপে, সমস্ত ফলাফল t1ফিরে আসে, এবং যদি কোনও মিল t2থাকে তবে তাও ফিরে আসে। যদি t2প্রদত্ত সারির জন্য কোনও মিল না থাকে t1, তবে কোয়েরিটি এখনও সারিটি দেয় t1এবং NULLসমস্ত t2কলামের স্থানধারক হিসাবে ব্যবহার করে । সাধারণভাবে বাহ্যিকভাবে যোগ দেয় এমনভাবেই।

এই ক্যোয়ারীতে কৌতুক এর ম্যাচিং শর্ত যেমন যে যোগদানের ডিজাইন করতে হয় t2মেলানো একই userid , এবং একটি বৃহত্তর date । ধারণা একটি সারিতে যদি উপস্থিত থাকে হচ্ছে t2একটি বেশি date, তারপর সারি t1বিরুদ্ধে তুলনা হচ্ছে করতে পারবেন বড় বলা হবে dateযে জন্য userid। তবে যদি কোনও মিল না থাকে - অর্থাত্ যদি কোনও সারি এর চেয়ে t2বড় সারিটির সাথে উপস্থিত না থাকে - আমরা জানি যে সারিটি সারিটি প্রদত্তদের জন্য সর্বাধিক সহ সারি ছিল ।datet1t1dateuserid

এই ক্ষেত্রে (যখন কোনও মিল নেই), এর কলামগুলি t2হবে NULL- এমনকি যোগদানের শর্তে নির্দিষ্ট কলামগুলিও। সুতরাং আমরা কেন ব্যবহার করি WHERE t2.UserId IS NULL, কারণ আমরা সেই ক্ষেত্রে অনুসন্ধান করছি যেখানে প্রদত্তর dateজন্য বৃহত্তর কোনও সারি পাওয়া যায় নি userid


7
বাহ বিল। এটি আমি দেখেছি এই সমস্যার সৃজনশীল সমাধান। এটি আমার মোটামুটি বড় ডেটা সেটটিতেও বেশ পারফরম্যান্ট। এটি নিশ্চিতভাবেই আমি দেখেছি এমন আরও অনেক সমাধানকে বা এই বিশৃঙ্খলা সমাধানের জন্য আমার নিজের প্রচেষ্টাকে মারধর করে।
জাস্টিন নোয়েল

36
৮.৮ মিলিয়ন সারি থাকা কোনও টেবিলে প্রয়োগ করা হলে, এই কোয়েরিটি গৃহীত উত্তরের তুলনায় প্রায় দ্বিগুণ হয়ে গেছে।
ডেরেক মাহর

16
@ ডেরেক: অপ্টিমাইজেশনগুলি আরডিবিএমএসের ব্র্যান্ড এবং সংস্করণ, পাশাপাশি যথাযথ সূচকগুলি, ডেটা ধরণের ইত্যাদির উপর নির্ভর করে
বিল কারভিন

7
মাইএসকিউএলে, এই ধরণের কোয়েরিটি কার্টেসিয়ান টেবিলগুলির মধ্যে যোগদানের ফলে ও (n ^ 2) সময়ের ফলস্বরূপ লুপ হওয়ার কারণ হিসাবে উপস্থিত হয়। সাবকিউরি পদ্ধতিটি ব্যবহারের পরিবর্তে ক্যোয়ারির সময়কে 2.0 থেকে 0.003 এস এড়িয়ে গেছে। YMMV।
জেসি

1
সারি সারিগুলিতে এটি খাপ খাইয়ে দেওয়ার কোনও উপায় আছে যেখানে তারিখটি কোনও প্রদত্ত তারিখের চেয়ে কম বা সমান তারিখ? উদাহরণস্বরূপ, যদি ব্যবহারকারী "23-OCT-2011" তারিখটি দেয় এবং সারণীতে "24-OCT-2011", "22-OCT-2011", "20-OCT-2011" এর জন্য সারি অন্তর্ভুক্ত থাকে তবে আমি চাই "22-OCT-2011" পান। আমার মাথার চুল আছড়ে পড়েছে এবং এই স্নিপেটটি এখনই পড়ছে ...
কোরি কেন্ডল

164
SELECT userid, MAX(value) KEEP (DENSE_RANK FIRST ORDER BY date DESC)
  FROM table
  GROUP BY userid

3
আমার পরীক্ষাগুলিতে একটি বৃহত সংখ্যক সারি থাকা একটি টেবিল ব্যবহার করে, এই সমাধানটি গ্রহণযোগ্য উত্তরের চেয়ে প্রায় দ্বিগুণ সময় নিয়েছিল।
ডেরেক মাহর

7
আপনার পরীক্ষাটি দেখান, দয়া করে
রব ভ্যান বিজক

আমি নিশ্চিত করেছি যে এটি অন্যান্য সমাধানগুলির চেয়ে অনেক দ্রুত
টেমারসালাম

5
সমস্যাটি হ'ল এটি সম্পূর্ণ রেকর্ডটি ফিরিয়ে দেয় না
Used_By_Alday

@ user2067753 না, এটি সম্পূর্ণ রেকর্ডটি ফেরত দেয় না। আপনি একাধিক কলামে একই MAX () .. KEEP .. এক্সপ্রেশন ব্যবহার করতে পারেন, যাতে আপনার প্রয়োজনীয় সমস্ত কলামগুলি নির্বাচন করতে পারেন। তবে আপনি যদি বিপুল সংখ্যক কলাম চান এবং সেলেক্ট * ব্যবহার করতে পছন্দ করেন তবে এটি অসুবিধাজনক।
ডেভ কোস্টা

51

আমি আপনার সঠিক কলামের নাম জানি না, তবে এটি এমন কিছু হবে:

    ব্যবহারকারী, মান নির্বাচন করুন
      ব্যবহারকারীদের থেকে u1
     যেখানে তারিখ = (সর্বোচ্চ (তারিখ নির্বাচন করুন)
                     ব্যবহারকারীদের থেকে u2
                    যেখানে u1.userid = u2.userid)

3
সম্ভবত খুব কার্যকর নয় স্টিভ।
ডেভিড অলড্রিজ

7
আপনি সম্ভবত ওরাকল ক্যোয়ারী অপ্টিমাইজারকে অবমূল্যায়ন করছেন।
রাফা ডাউগার্ড

3
একদমই না. তারিখগুলি পাওয়ার জন্য এটি অবশ্যই নেস্টেড লুপের সাথে একটি সম্পূর্ণ স্ক্যান হিসাবে প্রয়োগ করা হবে। আপনি টেবিলের সারিগুলির সংখ্যার চারগুণ অনুসারে লজিকাল আইও এর বিষয়ে কথা বলছেন এবং অ-তুচ্ছ পরিমাণে ডেটার জন্য ভীতিজনক হন।
ডেভিড অলড্রিজ

4
এফওয়াইআই, "দক্ষ নয়, তবে কাজ করে" "ওয়ার্কস, তবে দক্ষ নয়" as আমরা কখন ডিজাইনের লক্ষ্য হিসাবে দক্ষতাকে ছেড়ে দিয়েছি?
ডেভিড অলড্রিজ

6
+1 কারণ যখন আপনার ডেটাটেবলগুলি কয়েক মিলিয়ন সারি দৈর্ঘ্যের নতুন নয়, তখন এটি সর্বাধিক সহজে বোঝা যায় সমাধান। আপনার কোডটি সংশোধন করার জন্য সমস্ত দক্ষতার স্তরের একাধিক বিকাশকারী যখন রয়েছে তখন বোধগম্যতা আরও গুরুত্বপূর্ণ তখন পারফরম্যান্সে সেকেন্ডের একটি ভগ্নাংশ যা অলক্ষিত নয়।
n00b

35

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

এরকম কিছু, সম্ভবত (কলামের তালিকাটি প্রথম বন্ধনী দেওয়া উচিত কিনা তা মনে করতে পারে না):

SELECT * 
FROM MyTable
WHERE (User, Date) IN
  ( SELECT User, MAX(Date) FROM MyTable GROUP BY User)

সম্পাদনা: বাস্তবের জন্য এটি কেবল চেষ্টা করে দেখুন:

SQL> create table MyTable (usr char(1), dt date);
SQL> insert into mytable values ('A','01-JAN-2009');
SQL> insert into mytable values ('B','01-JAN-2009');
SQL> insert into mytable values ('A', '31-DEC-2008');
SQL> insert into mytable values ('B', '31-DEC-2008');
SQL> select usr, dt from mytable
  2  where (usr, dt) in 
  3  ( select usr, max(dt) from mytable group by usr)
  4  /

U DT
- ---------
A 01-JAN-09
B 01-JAN-09

সুতরাং এটি কাজ করে, যদিও অন্য কোথাও উল্লিখিত কিছু নতুন-চমত্কার জিনিসগুলি আরও পারফরম্যান্সযুক্ত হতে পারে।


4
পোস্টগ্র্রেএসকিউএল এ এটিও দুর্দান্তভাবে কাজ করে। এবং আমি এর সরলতা এবং সাধারণতা পছন্দ করি - উপসূত্রটি "এখানে আমার মানদণ্ড" বলে জানিয়েছে, বহিরাগত কোয়েরিটি বলে "এবং আমি যে বিবরণগুলি দেখতে চাই তা এখানে"। +1 টি।
j_random_hacker

13

আমি জানি আপনি ওরাকল চেয়েছিলেন, তবে এসকিউএল 2005 এ আমরা এখন এটি ব্যবহার করি:


-- Single Value
;WITH ByDate
AS (
SELECT UserId, Value, ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY Date DESC) RowNum
FROM UserDates
)
SELECT UserId, Value
FROM ByDate
WHERE RowNum = 1

-- Multiple values where dates match
;WITH ByDate
AS (
SELECT UserId, Value, RANK() OVER (PARTITION BY UserId ORDER BY Date DESC) Rnk
FROM UserDates
)
SELECT UserId, Value
FROM ByDate
WHERE Rnk = 1

7

এটি পরীক্ষা করার জন্য আমার কাছে ওরাকল নেই, তবে সর্বাধিক দক্ষ সমাধান হ'ল বিশ্লেষণমূলক প্রশ্নগুলি ব্যবহার করা। এটি দেখতে কিছু দেখতে হবে:

SELECT DISTINCT
    UserId
  , MaxValue
FROM (
    SELECT UserId
      , FIRST (Value) Over (
          PARTITION BY UserId
          ORDER BY Date DESC
        ) MaxValue
    FROM SomeTable
  )

আমি সন্দেহ করি যে আপনি বাহ্যিক ক্যোয়ারী থেকে মুক্তি পেতে পারেন এবং অভ্যন্তরে আলাদা করে রাখতে পারেন তবে আমি নিশ্চিত নই। এরই মধ্যে আমি জানি এটি একটি কাজ করে।

যদি আপনি বিশ্লেষণমূলক প্রশ্নগুলি সম্পর্কে জানতে চান তবে আমি http://www.orafaq.com/node/55 এবং http://www.akadia.com/services/ora_analytic_function.html পড়ার পরামর্শ দেব । এখানে সংক্ষিপ্তসারটি দেওয়া হল।

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

এই ক্ষেত্রে এখানে অভ্যন্তরীণ কোয়েরিটি করে। পুরো ডেটাসেটটি ইউজারআইডির পরে তারিখ ডিইএসসি অনুসারে বাছাই করা হয়েছে। তারপরে এটি একটি পাসে এটি প্রক্রিয়া করে। প্রতিটি সারির জন্য আপনি ব্যবহারকারীর ID এবং সেই ইউজারআইডির জন্য প্রথম দেখা তারিখ ফিরিয়ে দেন (যেহেতু তারিখগুলি DESC অনুসারে সাজানো হয়, এটি সর্বোচ্চ তারিখ)। এটি আপনাকে সদৃশ সারি সহ আপনার উত্তর দেয়। তারপরে বাইরের DISTINCT স্কোয়াশগুলি সদৃশ।

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


প্রশ্নের পুরো উত্তর দেওয়ার জন্য আপনাকেও তারিখের মানটি ফেরত দিতে হবে। এর অর্থ যদি অন্য প্রথম_মূল্যের ধারাটি থাকে তবে আমি পরামর্শ দেব যে সমাধানটি হওয়া উচিত তার চেয়ে জটিল and এবং সর্বাধিক (তারিখ) ভিত্তিক বিশ্লেষণ পদ্ধতি আরও ভালভাবে পড়তে পারে।
ডেভিড অলড্রিজ

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

"প্রশ্ন বিবরণীতে তারিখ ফিরিয়ে দেওয়ার বিষয়ে কিছুই বলা হয়নি" ... হ্যাঁ, আপনি ঠিক বলেছেন। দুঃখিত। তবে আরও FIRST_VALUE ক্লোজ যুক্ত করা খুব দ্রুত অগোছালো হয়ে উঠবে। এটি একটি একক উইন্ডো বাছাই, তবে যদি আপনার এই সারিটির জন্য ফিরে আসতে 20 টি কলাম থাকে তবে আপনি ভেদ করার জন্য প্রচুর কোড লিখেছেন।
ডেভিড অলড্রিজ

আমার কাছে এটিও ঘটে যে এই সমাধানটি ডেটার জন্য অ-নিরোধক যেখানে একটি একক ইউজারিডে একাধিক সারি থাকে যার সর্বাধিক তারিখ এবং বিভিন্ন VALUE থাকে। যদিও উত্তর চেয়ে প্রশ্নের আরও একটি দোষ।
ডেভিড অলড্রিজ

1
আমি সম্মতি জানাই এটি বেদনাদায়ক ভার্জোজ। তবে কি সাধারণত এসকিউএল এর ক্ষেত্রে হয় না? এবং আপনি ঠিক বলেছেন যে সমাধানটি অ-সংঘবদ্ধ। বন্ধনগুলি মোকাবেলার একাধিক উপায় রয়েছে এবং কখনও কখনও প্রতিটি আপনি যা চান তা হ'ল।
ব্যবহারকারী 11318

6

কোয়ালিফির একটি ধারাটি সহজ এবং সর্বোত্তম উভয়ই হতে পারে না?

select userid, my_date, ...
from users
qualify rank() over (partition by userid order by my_date desc) = 1

প্রসঙ্গে, তেরদাটাতে এখানে এই কোয়ালিফাই সংস্করণের সাথে 17 এর দশকে এবং 'ইনলাইন ভিউ' / এল্ড্রিজে সমাধান # 1 সহ 23 এর দশকে এর একটি সুন্দর আকারের পরীক্ষা চলে।


1
এটি আমার মতে সেরা উত্তর। তবে যেসব rank()পরিস্থিতিতে সম্পর্ক রয়েছে সেখানে ফাংশনটি সম্পর্কে সতর্ক থাকুন । আপনি একাধিক দিয়ে শেষ করতে পারেন rank=1row_number()আপনি যদি সত্যিই কেবল একটি রেকর্ড ফিরে চান তবে ব্যবহার করা ভাল ।
কার্টবফোরহর্স

1
এছাড়াও, সচেতন থাকুন যে QUALIFYধারাটি তেরদাতার সাথে নির্দিষ্ট। ওরাকলে (কমপক্ষে) আপনার মোড়কির বাছাই করতে WHEREহবে এবং মোড়কের নির্বাচনের স্টেটমেন্টের একটি ধারা ব্যবহার করে ফিল্টার করতে হবে (যা সম্ভবত পারফরম্যান্সকে স্পর্শ করে, আমি কল্পনাও করতে পারি)।
কার্টবফরহর্স

5

ইন Oracle 12c+, আপনি সাবকিউরিটি ছাড়াই খুব সংক্ষিপ্তভাবে এটি অর্জনের জন্য বিশ্লেষণমূলক ফাংশন সহ শীর্ষ এন প্রশ্নগুলি ব্যবহার করতে পারেন :rank

select *
from your_table
order by rank() over (partition by user_id order by my_date desc)
fetch first 1 row with ties;

উপরেরগুলি প্রতি ব্যবহারকারীকে সর্বাধিক মাই_ডেট দিয়ে সমস্ত সারি প্রদান করে।

আপনি যদি সর্বোচ্চ তারিখের সাথে কেবল একটি সারি চান, তবে এর rankসাথে প্রতিস্থাপন করুন row_number:

select *
from your_table
order by row_number() over (partition by user_id order by my_date desc)
fetch first 1 row with ties; 

5

প্রত্যেকের জন্য ROW_NUMBER()অবতরণ করার জন্য একটি অনন্য র‌্যাঙ্কিং বরাদ্দ করতে ব্যবহার করুন , তারপরে প্রত্যেকের জন্য প্রথম সারিতে ফিল্টার করুন (অর্থাত্, = 1)।DateUserIdUserIdROW_NUMBER

SELECT UserId, Value, Date
FROM (SELECT UserId, Value, Date,
        ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY Date DESC) rn
      FROM users) u
WHERE rn = 1;

5

PostgreSQL 8.4 বা তারপরে, আপনি এটি ব্যবহার করতে পারেন:

select user_id, user_value_1, user_value_2
  from (select user_id, user_value_1, user_value_2, row_number()
          over (partition by user_id order by user_date desc) 
        from users) as r
  where r.row_number=1

3

আপনি যে জিনিসটি আগের প্রশ্নের সাথে এই বৈকল্পিকটি দেখিয়েছেন তা হ'ল:

SELECT UserId, Value FROM Users U1 WHERE 
Date = ( SELECT MAX(Date)    FROM Users where UserId = U1.UserId)

3
Select  
   UserID,  
   Value,  
   Date  
From  
   Table,  
   (  
      Select  
          UserID,  
          Max(Date) as MDate  
      From  
          Table  
      Group by  
          UserID  
    ) as subQuery  
Where  
   Table.UserID = subQuery.UserID and  
   Table.Date = subQuery.mDate  

3

কাজের সময়ে কেবল একটি "লাইভ" উদাহরণ লিখতে হয়েছিল :)

এটি একই তারিখে ইউজারআইডির জন্য একাধিক মানকে সমর্থন করে ।

কলাম: ইউজারআইডি, মান, তারিখ

SELECT
   DISTINCT UserId,
   MAX(Date) OVER (PARTITION BY UserId ORDER BY Date DESC),
   MAX(Values) OVER (PARTITION BY UserId ORDER BY Date DESC)
FROM
(
   SELECT UserId, Date, SUM(Value) As Values
   FROM <<table_name>>
   GROUP BY UserId, Date
)

আপনি MAX এর পরিবর্তে FIRST_VALUE ব্যবহার করতে পারেন এবং ব্যাখ্যা পরিকল্পনায় এটি সন্ধান করতে পারেন। এটি নিয়ে খেলার সময় আমার ছিল না।

অবশ্যই, যদি বিশাল টেবিলগুলির মাধ্যমে অনুসন্ধান করা হয় তবে আপনি যদি আপনার ক্যোয়ারিতে পুরো ইঙ্গিতগুলি ব্যবহার করেন তবে এটি সম্ভবত আরও ভাল।


3
select VALUE from TABLE1 where TIME = 
   (select max(TIME) from TABLE1 where DATE= 
   (select max(DATE) from TABLE1 where CRITERIA=CRITERIA))

2

আমি এই জাতীয় কিছু মনে করি। (যে কোনও সিনট্যাক্স ভুলের জন্য আমাকে ক্ষমা করুন; আমি এই মুহুর্তে এইচকিউএল ব্যবহার করতে অভ্যস্ত!)

সম্পাদনা: প্রশ্নটিও ভুলভাবে পড়ে! ক্যোয়ারী সংশোধন করা হয়েছে ...

SELECT UserId, Value
FROM Users AS user
WHERE Date = (
    SELECT MAX(Date)
    FROM Users AS maxtest
    WHERE maxtest.UserId = user.UserId
)

"প্রতিটি ব্যবহারকারীর জন্য" শর্তটি পূরণ করে না
ডেভিড অলড্রিজ

কোথায় ব্যর্থ হবে? ব্যবহারকারীদের প্রতিটি ইউজারআইডি-র জন্য, এটির গ্যারান্টি দেওয়া হবে যে সেই ইউজারআইডি অন্তত একটি সারি ফিরিয়ে দেওয়া হবে। বা আমি কোথাও একটি বিশেষ মামলা মিস করছি?
jdmichal

2

(টি-এসকিউএল) প্রথমে সমস্ত ব্যবহারকারী এবং তাদের সর্বোচ্চ তারিখ পান। সর্বাধিক তারিখে থাকা ব্যবহারকারীদের জন্য সংশ্লিষ্ট মানগুলি সারণিতে যোগ দিন।

create table users (userid int , value int , date datetime)
insert into users values (1, 1, '20010101')
insert into users values (1, 2, '20020101')
insert into users values (2, 1, '20010101')
insert into users values (2, 3, '20030101')

select T1.userid, T1.value, T1.date 
    from users T1,
    (select max(date) as maxdate, userid from users group by userid) T2    
    where T1.userid= T2.userid and T1.date = T2.maxdate

ফলাফল:

userid      value       date                                    
----------- ----------- -------------------------- 
2           3           2003-01-01 00:00:00.000
1           2           2002-01-01 00:00:00.000

2

এখানে উত্তরটি কেবল ওরাকল। সমস্ত এসকিউএল-এ এখানে আরও কিছু পরিশীলিত উত্তর দেওয়া হয়েছে:

কার সামগ্রিকভাবে হোমওয়ার্কের ফলাফল (সর্বাধিক হোমওয়ার্ক পয়েন্ট)?

SELECT FIRST, LAST, SUM(POINTS) AS TOTAL
FROM STUDENTS S, RESULTS R
WHERE S.SID = R.SID AND R.CAT = 'H'
GROUP BY S.SID, FIRST, LAST
HAVING SUM(POINTS) >= ALL (SELECT SUM (POINTS)
FROM RESULTS
WHERE CAT = 'H'
GROUP BY SID)

এবং আরও কঠিন উদাহরণ, যার কিছুটা ব্যাখ্যা দরকার, যার জন্য আমার সময়ম এটিএম নেই:

২০০৮ সালে সবচেয়ে বেশি জনপ্রিয় (ISBN এবং শিরোনাম) বইটি দিন, যা ২০০৮ সালে প্রায়শই ধার করা হয়।

SELECT X.ISBN, X.title, X.loans
FROM (SELECT Book.ISBN, Book.title, count(Loan.dateTimeOut) AS loans
FROM CatalogEntry Book
LEFT JOIN BookOnShelf Copy
ON Book.bookId = Copy.bookId
LEFT JOIN (SELECT * FROM Loan WHERE YEAR(Loan.dateTimeOut) = 2008) Loan 
ON Copy.copyId = Loan.copyId
GROUP BY Book.title) X
HAVING loans >= ALL (SELECT count(Loan.dateTimeOut) AS loans
FROM CatalogEntry Book
LEFT JOIN BookOnShelf Copy
ON Book.bookId = Copy.bookId
LEFT JOIN (SELECT * FROM Loan WHERE YEAR(Loan.dateTimeOut) = 2008) Loan 
ON Copy.copyId = Loan.copyId
GROUP BY Book.title);

আশা করি এটি (যে কেউ) সাহায্য করবে .. :)

শুভেচ্ছা, গাস


গৃহীত উত্তরটি কেবল "ওরাকল" নয় - এটি স্ট্যান্ডার্ড এসকিউএল (অনেকগুলি ডিবিএমএস দ্বারা সমর্থিত)
a_horse_with_no_name

2

প্রদত্ত তারিখটি প্রদত্ত ইউজারআইডিএডের জন্য স্বতন্ত্র, এখানে কয়েকটি টিএসকিউএল রয়েছে:

SELECT 
    UserTest.UserID, UserTest.Value
FROM UserTest
INNER JOIN
(
    SELECT UserID, MAX(Date) MaxDate
    FROM UserTest
    GROUP BY UserID
) Dates
ON UserTest.UserID = Dates.UserID
AND UserTest.Date = Dates.MaxDate 

2

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

select
    userid,
    to_number(substr(max(to_char(date,'yyyymmdd') || to_char(value)), 9)) as value,
    max(date) as date
from 
    users
group by
    userid

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


এটি বেশিরভাগের তুলনায় একটি ভাল সম্পাদন পরিকল্পনা, তবে সেই সমস্ত কৌশলগুলি আরও প্রয়োগ করা হলে কয়েকটি ক্ষেত্র বিরক্তিকর হবে এবং এর বিরুদ্ধে কাজ করতে পারে। তবে খুব আকর্ষণীয় - ধন্যবাদ। স্ক্লাফিল্ডল
2749b5/

আপনি ঠিক বলেছেন এটি ক্লান্তিকর হয়ে উঠতে পারে, এ কারণেই যখন কোয়েরির পারফরম্যান্সটির প্রয়োজন হয় তখন এটি করা উচিত। ইটিএল স্ক্রিপ্টগুলির ক্ষেত্রে প্রায়শই এটি ঘটে।
aLevelOfIndirection

এই খুব সুন্দর. লিস্ট্যাগ ব্যবহার করে অনুরূপ কিছু করেছে তবে দেখতে কুৎসিত। অ্যারে_্যাগ ব্যবহার করে পোস্টগ্রিসের আরও ভাল বিন্যাস রয়েছে। আমার উত্তর দেখুন :)
ব্রুনো Calza

1
select userid, value, date
  from thetable t1 ,
       ( select t2.userid, max(t2.date) date2 
           from thetable t2 
          group by t2.userid ) t3
 where t3.userid t1.userid and
       t3.date2 = t1.date

আইএমএইচও এটি কাজ করে। আছে HTH


1

আমি এই কাজ করা উচিত?

Select
T1.UserId,
(Select Top 1 T2.Value From Table T2 Where T2.UserId = T1.UserId Order By Date Desc) As 'Value'
From
Table T1
Group By
T1.UserId
Order By
T1.UserId

1

প্রথমে উত্তরটি অনুসরণ করে আমি প্রশ্নটি ভুলভাবে লিখতে চেষ্টা করব, এখানে সঠিক ফলাফল সহ একটি সম্পূর্ণ উদাহরণ:

CREATE TABLE table_name (id int, the_value varchar(2), the_date datetime);

INSERT INTO table_name (id,the_value,the_date) VALUES(1 ,'a','1/1/2000');
INSERT INTO table_name (id,the_value,the_date) VALUES(1 ,'b','2/2/2002');
INSERT INTO table_name (id,the_value,the_date) VALUES(2 ,'c','1/1/2000');
INSERT INTO table_name (id,the_value,the_date) VALUES(2 ,'d','3/3/2003');
INSERT INTO table_name (id,the_value,the_date) VALUES(2 ,'e','3/3/2003');

-

  select id, the_value
      from table_name u1
      where the_date = (select max(the_date)
                     from table_name u2
                     where u1.id = u2.id)

-

id          the_value
----------- ---------
2           d
2           e
1           b

(3 row(s) affected)

1

এটি সদৃশদেরও যত্ন নেবে (প্রতিটি ব্যবহারকারীর জন্য একটি সারি ফেরত দাও):

SELECT *
FROM (
  SELECT u.*, FIRST_VALUE(u.rowid) OVER(PARTITION BY u.user_id ORDER BY u.date DESC) AS last_rowid
  FROM users u
) u2
WHERE u2.rowid = u2.last_rowid

1

এটি কেবল পরীক্ষা করা হয়েছে এবং এটি লগিং টেবিলটিতে কাজ করছে বলে মনে হচ্ছে

select ColumnNames, max(DateColumn) from log  group by ColumnNames order by 1 desc

1

এটি যেমন সহজ হতে হবে:

SELECT UserId, Value
FROM Users u
WHERE Date = (SELECT MAX(Date) FROM Users WHERE UserID = u.UserID)

1

মাইএসকিউএল এর জন্য সমাধান যা পার্টিশন কেইইপি, DENSE_RANK ধারণা নেই।

select userid,
       my_date,
       ...
from
(
select @sno:= case when @pid<>userid then 0
                    else @sno+1
    end as serialnumber, 
    @pid:=userid,
       my_Date,
       ...
from   users order by userid, my_date
) a
where a.serialnumber=0

তথ্যসূত্র: http://benincampus.blogspot.com/2013/08/select-rows- which-have-maxmin-value-in.html


এটি " অন্যান্য ডিবিগুলিতেও " কাজ করে না । এটি কেবল মাইএসকিউএল এবং সম্ভবত এসকিউএল সার্ভারে কাজ করে কারণ এর ভেরিয়েবলগুলির একই ধারণা রয়েছে। এটি অবশ্যই ওরাকল, পোস্টগ্রিস, ডিবি 2, ডার্বি, এইচ 2, এইচএসকিউএলডিবি, ভার্টিকা, গ্রিনপ্লামে কাজ করবে না। অতিরিক্তভাবে স্বীকৃত উত্তরটি হ'ল স্ট্যান্ডার্ড এএনএসআই এসকিউএল (যা কেবলমাত্র মাইএসকিউএল সমর্থন করে না)
a_horse_with_no_name

ঘোড়া, আমার ধারণা তুমি ঠিক আছ অন্যান্য ডিবি, বা এএনএসআই সম্পর্কে আমার জ্ঞান নেই। আমার সমাধানটি মাইএসকিউএলে সমস্যাটি সমাধান করতে সক্ষম, যার এএনএসআই এসকিউএলকে স্ট্যান্ডার্ড উপায়ে সমাধান করার জন্য উপযুক্ত সমর্থন নেই।
বেন লিন

1

আপনি যদি পোস্টগ্রিস ব্যবহার করছেন তবে আপনি এর array_aggমতো ব্যবহার করতে পারেন

SELECT userid,MAX(adate),(array_agg(value ORDER BY adate DESC))[1] as value
FROM YOURTABLE
GROUP BY userid

আমি ওরাকলের সাথে পরিচিত নই। এটিই আমি নিয়ে এসেছি

SELECT 
  userid,
  MAX(adate),
  SUBSTR(
    (LISTAGG(value, ',') WITHIN GROUP (ORDER BY adate DESC)),
    0,
    INSTR((LISTAGG(value, ',') WITHIN GROUP (ORDER BY adate DESC)), ',')-1
  ) as value 
FROM YOURTABLE
GROUP BY userid 

উভয় প্রশ্নেরই গৃহীত উত্তর হিসাবে একই ফলাফল ফেরত দেয়। এসকিউএলফিডলস দেখুন:

  1. উত্তর গৃহীত
  2. পোস্টগ্রিসের সাথে আমার সমাধান
  3. ওরাকলের সাথে আমার সমাধান

0

যদি (ইউজারআইডি, তারিখ) স্বতন্ত্র হয়, তবে একই ব্যবহারকারীর জন্য কোনও তারিখ দু'বার প্রদর্শিত হয় না:

select TheTable.UserID, TheTable.Value
from TheTable inner join (select UserID, max([Date]) MaxDate
                          from TheTable
                          group by UserID) UserMaxDate
     on TheTable.UserID = UserMaxDate.UserID
        TheTable.[Date] = UserMaxDate.MaxDate;

আমি বিশ্বাস করি যে আপনারও ইউজারআইডি-র সাথে যোগ দিতে হবে
টম এইচ

0
select   UserId,max(Date) over (partition by UserId) value from users;

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