নীচের সর্বাধিক সারিগুলি কীভাবে নির্বাচন করবেন?


100

আমি সেল্ট টপ (200) করতে পারি ... তবে বটম (200) কেন নয়?

আমি যা বোঝাতে চাইছি তা দর্শনে না গিয়ে, আমি কীভাবে শীর্ষের (200) সমতুল্যটি করতে পারি তবে বিপরীতে (নীচ থেকে, যেমন আপনি বটমটি আশা করবেন ...)?

উত্তর:


89
SELECT
    columns
FROM
(
     SELECT TOP 200
          columns
     FROM
          My_Table
     ORDER BY
          a_column DESC
) SQ
ORDER BY
     a_column ASC

2
কেন আপনি একটি উত্সাহিত টেবিল ব্যবহার করছেন?
রিচার্ডড

14
আপনি যদি এ-> জেড ক্রমে সারিগুলি ফিরিয়ে দিতে চান তবে জেড-> একটি আদেশে শীর্ষ 200 নির্বাচন করুন এটি করার এক উপায় এটি। অন্যান্য উত্তরগুলি, কেবল অর্ডার বদলে প্রস্তাব পরিবর্তন করার ফলে প্রশ্নটিতে বর্ণিত একই ফলাফলগুলি ফিরে আসবে না, কারণ তারা আদেশের বাইরে চলে যাবে (যদি না আদেশের বিষয়টি বিবেচনা না করে, যা ওপি বলেনি)।
টম এইচ

3
@ টম এইচ। আপনি কী বোঝাতে চেয়েছিলেন কয়েক সেকেন্ডের জন্য চিন্তা করতে হয়েছিল (আমি 14 ঘন্টা পর্যন্ত হয়েছি)। প্রথমে আমি উত্তর দিয়ে আপনার এবং অর্ডারের মধ্যে পার্থক্য দেখতে পেলাম না, তবে এখন আমি পারছি। সুতরাং +1।
রিচার্ডড

1
আপনি যখন ছোট টেবিলে কাজ করছেন তখন এই এবং অন্যান্য উত্তরগুলি ঠিকঠাক কাজ করে। আপনি যখন নীচের কয়েকটি সারিটিতে আগ্রহী হন তখন কলামটি দিয়ে পুরো টেবিলটি অর্ডার করা উপযুক্ত বলে মনে করি না।
স্ট্যাডিফিশ

1
ভাল উত্তর, সেরা ইমো ... আসল সমস্যাটি হ'ল আমি এটিএসপি স্ক্রিপ্ট থেকে এটি করতে পারি না, তাই আমার মনে হয় আমাকে নিজেই পুনরায় অর্ডার করা দরকার বা এএসপি প্রদত্ত ফাংশনটি দিয়ে ....
আন্দ্রে_86৮

99

এটি অপ্রয়োজনীয়। আপনি একটি ব্যবহার করতে পারেন ORDER BYএবং DESCএকই প্রভাবটি পেতে কেবল বাছাই করতে পারেন।


3
গুগল একই কথা বলেছিল এবং এখন আপনি 9 জন একমত, আমার পক্ষে যথেষ্ট ভাল, ধন্যবাদ: ডি
ক্লাউডমেটা

8
ডিইএসসি ব্যবহার করে সর্বশেষ এন সারিগুলি ফিরে আসবে, তবে ফিরে আসা সারিগুলিও প্রথম এন সারি থেকে বিপরীত ক্রমে থাকবে।
রিকএনজেড

11
আপনার টেবিলে অর্ডারের মাধ্যমে কোনও সূচক না থাকলে কী হবে?
রক্ষক এক

8
@ জাস্টিন: কেবলমাত্র একটি কলাম রয়েছে যার মধ্যে বর্ণের মান রয়েছে gine অর্ডার দ্বারা বর্ণমালা অনুসারে বাছাই করা হত যা আমরা সম্ভবত যা চাই তা নয় (সম্ভবত)।
রক্ষক এক

3
টম এইচ হ'ল সঠিক আনউসার, অন্যথায়, আপনার সারিগুলি বিপরীত ক্রমে থাকবে।
পিয়েরে-অলিভিয়ের গাউলেট

39

দুঃখিত, তবে আমি মনে করি না আমি আমার মতে কোনও সঠিক উত্তর দেখতে পাচ্ছি।

TOPএক্স শো অনির্ধারিত অনুক্রমে রেকর্ড কাজ করে। যে সংজ্ঞা থেকে একটি BOTTOMফাংশন সংজ্ঞায়িত করা যায় না যে অনুসরণ করে ।

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

  • এটি কেবল তখনই কাজ করে যদি কোনও অটোজেনারেটেড আইডি কলাম থাকে
  • যদি আপনি এটি TOPফাংশনটির সাথে তুলনা করেন তবে এটির একটি উল্লেখযোগ্য পারফরম্যান্স প্রভাব রয়েছে

সঠিক উত্তরটি এমন হওয়া উচিত যে TOPনীচের সারিগুলি পাওয়ার জন্য সমতুল্য নেই, এবং হতে পারে না ।


3
সত্য, কোনও সমতুল্য বলে মনে হচ্ছে না, কেবলমাত্র কাজের ক্ষেত্র।
অকর্মা

4
টপকে কোন টেবিলের সাথে আইটেমগুলি যুক্ত করা হয়েছিল তার সাথে শীর্ষগুলির কোনও সম্পর্ক নেই, এর অর্থ হ'ল "আমার প্রশ্নের সাথে মেলে এমন প্রথম এক্স রেকর্ড দিন"
লূক

4
হ্যাঁ এটি করে, এটি আপনাকে সারণীতে যুক্ত রেকর্ডগুলি দেয় যা আপনার প্রশ্নের সাথে মেলে।
মার্টিজন বার্গার

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

2
আমি এই উত্তরের সাথে একমত, তবে বাস্তবে টমের উত্তর সমস্ত ব্যবহারিক ব্যবহারের জন্য সমস্যার সমাধান করে।
আন্তোনিও

18

কথাটি,

BOTTOM (x) is all the records except TOP (n - x), where n is the count; x <= n

উদাহরণস্বরূপ কর্মচারী থেকে নীচে 1000 নির্বাচন করুন:

টি-এসকিউএল এ,

DECLARE 
@bottom int,
@count int

SET @bottom = 1000 
SET @count = (select COUNT(*) from Employee)

select * from Employee emp where emp.EmployeeID not in 
(
SELECT TOP (@count-@bottom) Employee.EmployeeID FROM Employee
)

1
হাই shadi2014, "অর্ডার বাই" ব্যবহার না করে আপনার ফলাফলটি কোনওভাবে এলোমেলো হবে।
বম্মি

5
বমি, আপনি ঠিক বলেছেন, তবে এই উত্তরটি সঠিক করে তোলে। শীর্ষ নির্বাচন নিজেই তাত্ত্বিকভাবে "এলোমেলো" এবং এটি সিলেক্ট বটমটির জন্য সঠিক বাস্তবায়ন। 5000 রেকর্ডের একটি সারণীতে, নীচে 1000 শীর্ষ 4000 ব্যতীত সমস্ত কিছু
tzachs

9

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

শীর্ষস্থানীয় একটি নিরক্ষিত ক্যোয়ারী ফলাফল সেট প্রদান করে যা প্রথম এন রেকর্ডসকে রেকর্ড সেটটি সীমাবদ্ধ করে। (ওরাকল দৃষ্টিকোণ থেকে, এটি যেখানে রাউনুম <(এন + 1) যুক্ত করা সমান।

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

শীর্ষের কার্যকারিতা হ'ল একবার ডেটাসেটটি একটি নির্দিষ্ট আকার এন এ পৌঁছে যায়, এটি সারিগুলি আনা বন্ধ করে দেয়। এগুলি সমস্ত এনে না নিয়ে ডেটা দেখতে কেমন লাগে তার জন্য আপনি একটি অনুভূতি পেতে পারেন।

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

একইভাবে, যে সমাধানগুলি অর্ডার দ্বারা বাস্তবায়ন করে সেগুলি হ'ল দুর্ভাগ্যক্রমে, বড় ডেটা সেটগুলির সাথে কাজ করার সময় সম্ভাব্য বিপর্যয়কর। যদি আমার কাছে বলুন, 10 বিলিয়ন রেকর্ড রয়েছে এবং সর্বশেষ 10 চান তবে এটি 10 ​​বিলিয়ন রেকর্ড অর্ডার করা এবং শেষ 10 নির্বাচন করা যথেষ্ট বোকামি।

এখানে সমস্যাটি হ'ল, বটটমের সাথে টপ এর সাথে তুলনা করার সময় আমরা যে অর্থটি মনে করি তার অর্থ হয় না ।

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

সুতরাং - এখানে নীচের লাইনটি (পাং উদ্দেশ্যযুক্ত) হ'ল যে কেউ বটম এন রেকর্ডের জন্য জিজ্ঞাসা করছে তারা আসলে কী জানতে চাইছে তা জানে না। বা, কমপক্ষে, তারা কী জন্য জিজ্ঞাসা করছে এবং বটটম আসলে কী বোঝায় তা একই জিনিস নয়।

সুতরাং - সমাধানটি অনুরোধকারকের আসল ব্যবসায়ের প্রয়োজন মেটাতে পারে ... তবে বটম হওয়ার মানদণ্ডটি পূরণ করে না।


1
দুর্দান্ত ব্যাখ্যা। বিষয়টিতে আরও আলোকপাতের জন্য আপভোট করুন।
rohrl77

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

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

3

"জাস্টিন ইথিয়ার" দ্বারা বর্তমানে গৃহীত উত্তরটি "প্রোটেক্টর একজন" দ্বারা নির্দেশিত সঠিক উত্তর নয়।

যতদূর আমি দেখতে পাচ্ছি, এখন অবধি, অন্য কোনও উত্তর বা মন্তব্য প্রশ্নকার লেখকের কাছে জিজ্ঞাসা করা BOTTOM (x) এর সমতুল্য সরবরাহ করে না।

প্রথমে আসুন একটি দৃশ্য বিবেচনা করুন যেখানে এই কার্যকারিতাটির প্রয়োজন হবে:

SELECT * FROM Split('apple,orange,banana,apple,lime',',')

এটি একটি কলাম এবং পাঁচটি রেকর্ডের একটি সারণী প্রদান করে:

  • আপেল
  • কমলা
  • কলা
  • আপেল
  • চুন

আপনি দেখতে পাচ্ছেন: আমাদের আইডি কলাম নেই; আমরা ফিরে আসা কলাম দ্বারা অর্ডার করতে পারি না; এবং আমরা স্ট্যান্ডার্ড এসকিউএল ব্যবহার করে নীচের দুটি রেকর্ড নির্বাচন করতে পারি না যেমন আমরা শীর্ষ দুটি রেকর্ডের জন্য করতে পারি।

সমাধান দেওয়ার জন্য আমার চেষ্টাটি এখানে:

SELECT * INTO #mytemptable FROM Split('apple,orange,banana,apple,lime',',')
ALTER TABLE #mytemptable ADD tempID INT IDENTITY
SELECT TOP 2 * FROM #mytemptable ORDER BY tempID DESC
DROP TABLE #mytemptable

এবং এখানে আরও একটি সম্পূর্ণ সমাধান:

SELECT * INTO #mytemptable FROM Split('apple,orange,banana,apple,lime',',')
ALTER TABLE #mytemptable ADD tempID INT IDENTITY
DELETE FROM #mytemptable WHERE tempID <= ((SELECT COUNT(*) FROM #mytemptable) - 2)
ALTER TABLE #mytemptable DROP COLUMN tempID
SELECT * FROM #mytemptable
DROP TABLE #mytemptable

আমি দাবী করি না যে সমস্ত পরিস্থিতিতে এটি ব্যবহার করা ভাল ধারণা, তবে এটি পছন্দসই ফলাফল সরবরাহ করে।



1

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

DECLARE @NumberOfRows int;
SET @NumberOfRows = (SELECT COUNT(*) FROM TheTable);

SELECT col1, col2,...
FROM (
    SELECT col1, col2,..., ROW_NUMBER() OVER (ORDER BY col1) AS intRow
    FROM TheTable
) AS T
WHERE intRow > @NumberOfRows - 20;

2
1) যদি আপনার অর্ডার বাই ধারাটির দিক পরিবর্তন করে "সূচকগুলির ভাল ব্যবহার হয় না", তবে একটি শালীন আরডিবিএমএস পান! আরডিবিএমএস কখনই বিবেচ্য হবে না এটি সূচকটি এগিয়ে বা পিছনের দিকে চালিত করে। 2) আপনি সূচকগুলি ব্যবহার সম্পর্কে উদ্বিগ্ন, তবুও আপনার সমাধানটি টেবিলের প্রতিটি সারিতে একটি অনুক্রম সংযুক্ত করে ... উপযুক্ত সূচকটি গ্যারান্টিযুক্ত করার একটি উপায় এটি ব্যবহার করা হবে না।
বিস্মৃত

1

উপরের "টম এইচ" উত্তরটি সঠিক এবং এটি নীচে 5 টি সারি পাওয়ার জন্য আমার পক্ষে কাজ করে।

SELECT [KeyCol1], [KeyCol2], [Col3]
FROM
(SELECT TOP 5 [KeyCol1],
       [KeyCol2],
       [Col3]
  FROM [dbo].[table_name]
  ORDER BY [KeyCol1],[KeyCol2] DESC) SOME_ALAIS
  ORDER BY [KeyCol1],[KeyCol2] ASC

ধন্যবাদ।


0

এটা চেষ্টা কর.

declare @floor int --this is the offset from the bottom, the number of results to exclude
declare @resultLimit int --the number of results actually retrieved for use
declare @total int --just adds them up, the total number of results fetched initially

--following is for gathering top 60 results total, then getting rid of top 50. We only keep the last 10
set @floor = 50 
set @resultLimit = 10
set @total = @floor + @resultLimit

declare @tmp0 table(
    --table body
)

declare @tmp1 table(
    --table body
)

--this line will drop the wanted results from whatever table we're selecting from
insert into @tmp0
select Top @total --what to select (the where, from, etc)

--using floor, insert the part we don't want into the second tmp table
insert into @tmp1
select top @floor * from @tmp0

--using select except, exclude top x results from the query
select * from @tmp0
except 
select * from @tmp1

ওপির জন্য আপনার কোডটি কী করে? আপনি কীভাবে সমস্যাটি সমাধান করার চেষ্টা করছেন দয়া করে কিছুটা আরও ব্যাখ্যা যুক্ত করুন
টেকস্পাইডার

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

0

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

উদাহরণস্বরূপ, আপনি যদি সর্বশেষ 1 (বা 2, বা 5, বা 34) ব্যতীত কোনও সারণীতে লগইন করা সমস্ত অবস্থান পেতে চান

SELECT * 
FROM
    (SELECT ROW_NUMBER() OVER (ORDER BY CreatedDate) AS Row, * 
    FROM Locations
    WHERE UserId = 12345) AS SubQuery
WHERE Row > 1 -- or 2, or 5, or 34

0

একটি সাধারণ সাবকোয়ারি সাজানো অবতরণকে জিজ্ঞাসা করা, একই কলামে বাছাইয়ের পরে আরোহী কৌশলটি করে।

SELECT * FROM 
    (SELECT TOP 200 * FROM [table] t2 ORDER BY t2.[column] DESC) t1
    ORDER BY t1.[column]


0

প্রথমে টেবিলের মূল ক্রম অনুসারে একটি সাবকিউরিতে একটি সূচক তৈরি করুন:

ROW_NUMBER () OVER (ORDER BY (SELECT NULL) ) AS RowIndex

তারপরে RowIndexআপনি মুখ্য ক্যোয়ারিতে তৈরি কলামটি দিয়ে টেবিলটিকে অবতরণ করুন :

ORDER BY RowIndex DESC

এবং অবশেষে TOPআপনার প্রয়োজনীয় পরিমাণে সারি ব্যবহার করুন:

    SELECT TOP 1 * --(or 2, or 5, or 34)
    FROM   (SELECT ROW_NUMBER() OVER (ORDER BY  (SELECT NULL) ) AS RowIndex, * 
            FROM MyTable) AS SubQuery
    ORDER BY RowIndex DESC
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.