सबसे नीचे की पंक्तियों का चयन कैसे करें?


100

मैं Select TOP (200) कर सकता हूं ... लेकिन BOTTOM (200) क्यों नहीं?

अच्छी तरह से दर्शन में नहीं है कि मेरा क्या मतलब है, मैं TOP (200) के बराबर कैसे कर सकता हूं, लेकिन रिवर्स में (नीचे से, जैसे आप BOTTOM करने की उम्मीद करेंगे ...)?

जवाबों:


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

2
आप एक व्युत्पन्न तालिका का उपयोग क्यों कर रहे हैं?
रिचर्ड डेस

14
यदि आप A-> Z ऑर्डर में पंक्तियों को वापस करना चाहते हैं, लेकिन Z-> A ऑर्डर में शीर्ष 200 का चयन करें यह करने का एक तरीका है। अन्य उत्तर, केवल ORDER BY को बदलने का सुझाव देने से प्रश्न में वर्णित समान परिणाम वापस नहीं आएंगे, क्योंकि वे क्रम से बाहर हो जाएंगे (जब तक कि आदेश से कोई फर्क नहीं पड़ता, जो ओपी ने नहीं कहा था)।
टॉम एच

3
@ टॉम एच। को कुछ सेकंड के लिए सोचना था कि आप क्या कर रहे हैं (मुझे 14 घंटे हो गए हैं)। पहले तो मैं आपके और आदेश के बीच के अंतर को उत्तरों द्वारा नहीं देख सकता था, लेकिन अब मैं कर सकता हूं। तो +1।
रिचर्ड डेस

1
जब आप छोटी तालिकाओं पर काम कर रहे हों तो यह और अन्य उत्तर ठीक काम करते हैं। मुझे नहीं लगता कि जब आप नीचे की कुछ पंक्तियों में रुचि रखते हैं तो स्तंभ द्वारा संपूर्ण तालिका को क्रमबद्ध करने के लायक है।
स्टैन्फ़िश

1
अच्छा जवाब, सबसे अच्छा imho ... असली समस्या यह है कि मैं यह एक एएसपी स्क्रिप्ट से नहीं कर सकता, इसलिए मुझे लगता है कि मुझे मैन्युअल रूप से या एएसपी प्रदान करने वाले फ़ंक्शन के साथ objRecordset को फिर से व्यवस्थित करने की आवश्यकता है ...
Andrea_86

98

यह अनावश्यक है। आप एक का उपयोग कर सकते हैं ORDER BYऔर DESCसमान प्रभाव प्राप्त करने के लिए बस प्रकार को बदल सकते हैं ।


3
Google ने एक ही बात कही और अब आप में से 9 सहमत हैं, मेरे लिए काफी अच्छा है, धन्यवाद: D
CloudMeta

9
DESC का उपयोग करने से पिछली N पंक्तियाँ वापस आ जाएँगी, लेकिन लौटी पंक्तियाँ भी पहले N पंक्तियों से उल्टे क्रम में होंगी।
रिकएनजेड

11
क्या होगा अगर आपकी मेज पर ORDER BY का कोई इंडेक्स नहीं है?
रक्षा एक

8
@ जस्टिन: केवल एक कॉलम होने की कल्पना करें, जिसमें वर्चर वैल्यूज हों। ORDER BY वर्णानुक्रम में छांटेगा, जो कि (शायद) वह नहीं है जो हम चाहते हैं।
रक्षा एक

3
टॉम एच सही अन्वेषक है, अन्यथा, आपकी पंक्तियां रिवर्स ऑर्डर में होंगी।
पियरे-ओलिवियर गॉलेट

39

क्षमा करें, लेकिन मुझे नहीं लगता कि मुझे अपनी राय में कोई सही उत्तर दिखाई देता है।

TOPएक्स शो अपरिभाषित क्रम में रिकॉर्ड कार्य करते हैं। उस परिभाषा से इस प्रकार है कि एक BOTTOMफ़ंक्शन को परिभाषित नहीं किया जा सकता है।

किसी इंडेक्स या सॉर्ट क्रम से स्वतंत्र। जब आप करते हैं तो ORDER BY y DESCआपको सबसे पहले y मान वाली पंक्तियाँ मिलती हैं। यदि यह एक ऑटोजेनरेटेड आईडी है, तो इसे तालिका में पिछले रिकॉर्ड को दिखाना चाहिए, जैसा कि अन्य उत्तरों में सुझाया गया है। तथापि:

  • यह केवल तभी काम करता है जब कोई ऑटोजेनरेटेड आईडी कॉलम हो
  • यदि आप TOPफ़ंक्शन के साथ तुलना करते हैं तो इसका महत्वपूर्ण प्रदर्शन प्रभाव पड़ता है

सही उत्तर यह होना चाहिए कि TOPनीचे की पंक्तियों को प्राप्त करने के लिए एक समान नहीं है, और न ही हो सकता है ।


3
सच है, कोई समतुल्य नहीं लगता है, बस वर्कअराउंड है।
प्रहार

4
TOP का उस क्रम से कोई लेना-देना नहीं है, जिसमें आइटमों को एक तालिका में जोड़ा गया था, जिसका मतलब है "मेरी क्वेरी से मेल खाने वाले पहले एक्स रिकॉर्ड दें"
ल्यूक

4
हाँ यह करता है, यह आपको तालिका में जोड़े गए पहले रिकॉर्ड को बताता है जो आपकी क्वेरी से मेल खाता है।
मार्टिंज बर्गर

4
मैं ल्यूक से सहमत हूं। डाटाबेस टेबल परिभाषा के हिसाब से ऑर्डर-लेस हैं। RDBMS द्वारा दिए गए आदेश पर किसी को कभी भी भरोसा नहीं करना चाहिए, जब चयन कथन में कोई खंड नहीं है। विकी पर यहां पढ़ें हालांकि, डेटाबेस सिस्टम पंक्तियों के किसी भी क्रम की गारंटी नहीं देता है जब तक कि तालिका में प्रश्नों का चयन करने वाले कथन में एक ORDER BY खंड निर्दिष्ट नहीं किया जाता है।
ज़ोहर पे

2
मैं इस जवाब से सहमत हूं, लेकिन व्यवहार में टॉम का जवाब सभी व्यावहारिक उपयोगों के लिए समस्या को हल करता है।
एंटोनियो

18

तर्क में,

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

जैसे कर्मचारी से नीचे 1000 का चयन करें:

T-SQL में,

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, "ORDER BY" के उपयोग के बिना आपका परिणाम किसी तरह यादृच्छिक होगा।
बुम्मी

5
बुम्मी, आप सही कह रहे हैं, लेकिन जो इस जवाब को सही बनाता है। Select TOP स्वयं सिद्धांत रूप में "यादृच्छिक" है, और यह Select BOTTOM के लिए सही कार्यान्वयन है। 5000 रिकॉर्ड की तालिका में, नीचे का हिस्सा शीर्ष 4000 को छोड़कर सब कुछ है।
tzachs

9

ऐसा लगता है कि समाधान में एक आदेश द्वारा आदेश को लागू करने वाले किसी भी उत्तर में बिंदु गायब है, या वास्तव में यह समझ में नहीं आता है कि TOP आपके लिए क्या रिटर्न देता है।

शीर्ष रिटर्न एक अनियंत्रित क्वेरी परिणाम सेट करता है जो रिकॉर्ड सेट को पहले एन रिकॉर्ड किए गए रिटर्न तक सीमित करता है। (ओरेकल के नजरिए से, यह ROWNUM <(N + 1) को जोड़ने के समान है।

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

TOP की उपयोगिता यह है कि एक बार जब डेटासेट एक निश्चित आकार N तक पहुँच जाता है, तो यह पंक्तियों को लाना बंद कर देता है। आप यह महसूस कर सकते हैं कि यह सब प्राप्त किए बिना डेटा कैसा दिखता है।

BOTTOM को सही ढंग से लागू करने के लिए, इसे पूरे डेटासेट को अनियंत्रित करना होगा और फिर अंतिम एन रिकॉर्ड के लिए डेटासेट को प्रतिबंधित करना होगा। यदि आप बड़ी तालिकाओं के साथ काम कर रहे हैं तो यह विशेष रूप से प्रभावी नहीं होगा। और न ही यह आवश्यक रूप से आपको वह देगा जो आप सोचते हैं कि आप पूछ रहे हैं। जरूरी नहीं कि डेटा सेट का अंत "अंतिम पंक्तियों को सम्मिलित किया जाए" (और संभवतः अधिकांश डीएमएल गहन अनुप्रयोगों के लिए नहीं होगा)।

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

यहाँ समस्या यह है कि BOTTOM का यह अर्थ नहीं है कि हम इसे TOP से तुलना करते समय सोचते हैं

जब बार-बार रिकॉर्ड डाला जाता है, हटाया जाता है, डाला जाता है, बार-बार हटाया जाता है, तो स्टोरेज में कुछ अंतराल दिखाई देंगे और बाद में, यदि संभव हो तो, पंक्तियों को स्लाइन किया जाएगा। लेकिन जो हम अक्सर देखते हैं, जब हम TOP का चयन करते हैं, तो सॉर्ट किए गए डेटा दिखाई देते हैं, क्योंकि यह तालिका के अस्तित्व में जल्दी डाला जा सकता है। तालिका कई विलोपन का अनुभव नहीं है, तो यह हो सकता है दिखाई आदेश दिया जा करने के लिए। (उदाहरण के निर्माण की तारीखें समय के साथ ही वापस हो सकती हैं क्योंकि तालिका निर्माण स्वयं)। लेकिन वास्तविकता यह है कि अगर यह एक डिलीट-हेवी टेबल है, तो हो सकता है कि TOP N पंक्तियां ऐसी न दिखें।

यहाँ - नीचे की पंक्ति (यमक का उद्देश्य) यह है कि जो कोई BOTTOM N रिकॉर्ड के लिए पूछ रहा है वह वास्तव में नहीं जानता कि वे क्या मांग रहे हैं। या, कम से कम, वे जो पूछ रहे हैं और जो वास्तव में BOTTOM का मतलब है, वही बात नहीं है।

इसलिए - समाधान अनुरोधकर्ता की वास्तविक व्यावसायिक आवश्यकता को पूरा कर सकता है ... लेकिन BOTTOM होने के लिए मानदंडों को पूरा नहीं करता है।


1
बहुत बढ़िया स्पष्टीकरण। विषय पर अधिक प्रकाश डालने के लिए अपवोट करें।
rohrl77

मेरा उपयोग मामला यह है मैंने insertएक बड़ी, अनईन्डेक्स्ड टेबल में पंक्तियाँ डालने के लिए एक बड़ा बयान दिया। (मैं इसे अनुक्रमणित करने के लिए प्रारंभ करने से पहले तालिका को पहले से ही पॉप्युलेट कर रहा हूं।) मैंने अपने ग्राहक सत्र को रिबूट या जो भी हो, के कारण खो दिया है, और अब मैं यह देखना चाहता हूं कि क्या मेरी नई जोड़ी गई पंक्तियां वहां हैं। यदि टेबल की 'नीचे' पंक्ति मेरे हाल के लोगों में से एक है, तो मुझे पता है कि ऑपरेशन पूरा हो गया है। यदि 'नीचे' पंक्ति कुछ और है, तो कोई गारंटी नहीं है और मुझे यह सुनिश्चित करने के लिए पूरी तालिका को स्कैन करना होगा ... लेकिन सबसे अधिक संभावना है कि मैं 'नीचे' को जल्दी से जाँच कर कुछ समय बचा सकता हूं जैसे कि आप ' ऊपर'।
एड एविस

अच्छी व्याख्या, लेकिन यह अभी भी एक तल के अस्तित्व का तात्पर्य करता है, बस इसके लिए आवश्यक है कि डेटा को रिवर्स में पढ़ा / पुनर्प्राप्त किया जाए। एक नई मेज पर एक गर्भपात डालने का मामला (admitteedly बढ़त) में, सब कुछ प्राप्त करने के बिना पिछले रिकॉर्ड सम्मिलित (नीचे) सत्यापित करने से उपयोगी होगा। क्या कोई तकनीकी कारण है कि तालिका डेटा को रिवर्स ऑर्डर में पुनर्प्राप्त नहीं किया जा सकता है?
जेम्स

3

"जस्टिन एथियर" द्वारा वर्तमान में स्वीकृत उत्तर सही उत्तर नहीं है जैसा कि "रक्षक एक" द्वारा बताया गया है।

जहाँ तक मैं देख सकता हूँ, अब तक, कोई अन्य उत्तर या टिप्पणी BOTTOM (x) के बराबर नहीं प्रदान करता है जो प्रश्न लेखक ने पूछा है।

पहले, आइए एक परिदृश्य पर विचार करें जहां इस कार्यक्षमता की आवश्यकता होगी:

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

यह एक स्तंभ और पाँच अभिलेखों की तालिका लौटाता है:

  • सेब
  • संतरा
  • केला
  • सेब
  • चूना

जैसा कि आप देख सकते हैं: हमारे पास एक आईडी कॉलम नहीं है; हम दिए गए कॉलम द्वारा ऑर्डर नहीं कर सकते हैं; और हम मानक SQL का उपयोग करके नीचे के दो रिकॉर्ड का चयन नहीं कर सकते हैं जैसे हम शीर्ष दो रिकॉर्ड के लिए कर सकते हैं।

यहाँ एक समाधान प्रदान करने का मेरा प्रयास है:

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) यदि आपके आदेश द्वारा "खंडों का अच्छा उपयोग नहीं किया जाता है" तो अपने आदेश की दिशा बदल दें, तो एक अच्छा RDBMS प्राप्त करें! RDBMS को कभी भी परवाह नहीं करनी चाहिए कि यह सूचकांक को आगे या पीछे की ओर नेविगेट करता है या नहीं। 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 का चयन करता है, फिर शीर्ष x - संख्या का चयन करें, फिर अनपेक्षित परिणामों को छोड़ने के लिए एक बयान का उपयोग करके।
हम्बलेवडेव

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
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.