SELECT TOP (200) yapabilirim ... ama neden BOTTOM (200) olmasın?
Felsefeye girmemek için demek istediğim, TOP (200) 'ün eşdeğerini nasıl yapabilirim ama tersine (aşağıdan, BOTTOM'un yapmasını beklediğiniz gibi ...)?
Yanıtlar:
SELECT
columns
FROM
(
SELECT TOP 200
columns
FROM
My_Table
ORDER BY
a_column DESC
) SQ
ORDER BY
a_column ASC
Gereksizdir. Bir kullanabilir ORDER BY
ve DESC
aynı etkiyi elde etmek için sıralamayı değiştirebilirsiniz .
Üzgünüm ama bence herhangi bir doğru cevap göremediğimi düşünüyorum.
TOP
X yakalanan görünen tanımsız sırayla kayıtları çalışır. Bu tanımdan bir BOTTOM
fonksiyonun tanımlanamayacağı anlaşılır .
Herhangi bir dizinden veya sıralama düzeninden bağımsız. Bir yaptığınızda ORDER BY y DESC
, önce en yüksek y değerine sahip satırları alırsınız. Bu otomatik oluşturulmuş bir kimlik ise, diğer cevaplarda önerildiği gibi tabloya en son eklenen kayıtları göstermelidir. Ancak:
TOP
işlevle karşılaştırırsanız önemli bir performans etkisi vardır.Doğru cevap TOP
, alt satırları elde etmek için bir eşdeğer olmadığı ve olamaz olmalıdır .
Mantıksal olarak,
BOTTOM (x) is all the records except TOP (n - x), where n is the count; x <= n
Örneğin, Çalışandan Alt 1000'i seçin:
T-SQL'de,
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
)
Görünüşe göre çözümde ORDER BY cümlesini uygulayan yanıtlardan herhangi biri noktayı kaçırıyor veya TOP'un size ne döndürdüğünü gerçekten anlamıyor.
TOP, kayıt kümesini döndürülen ilk N kayıtla sınırlayan sırasız bir sorgu sonuç kümesi döndürür. (Oracle açısından bakıldığında, bir ROWNUM <(N + 1) eklemeye benzer.
Bir sipariş kullanan herhangi bir çözelti, olabilir tarafından amacıyla kullanılmıştır hangi kriterlere bağlı olarak, (bu veri seti, birinci etapta sırasız beri), UOP maddesi tarafından döndürülen satır döndürür
TOP'un faydası, veri kümesi belirli bir N boyutuna ulaştığında satırları getirmeyi durdurmasıdır. Hepsini almak zorunda kalmadan verilerin neye benzediğine dair bir fikir edinebilirsiniz.
BOTTOM'u doğru bir şekilde uygulamak için, tüm veri kümesini sırasız olarak getirmesi ve ardından veri kümesini son N kayıtla sınırlaması gerekir. Büyük masalarla uğraşıyorsanız bu özellikle etkili olmayacaktır. Size istediğinizi düşündüğünüz şeyi de vermeyecektir . Veri kümesinin sonu mutlaka "eklenen son satırlar" olmayabilir (ve muhtemelen DML yoğun uygulamaların çoğu için olmayacaktır).
Benzer şekilde, ORDER BY uygulayan çözümler, ne yazık ki, büyük veri kümeleriyle uğraşırken felaket olabilir. Diyelim ki 10 Milyar plağım varsa ve son 10'unu istiyorsam, 10 Milyar kayıt sipariş edip son 10'u seçmek oldukça aptalca.
Buradaki sorun, BOTTOM'un onu TOP ile karşılaştırırken düşündüğümüz anlama sahip olmamasıdır .
Kayıtlar tekrar tekrar eklendiğinde, silindiğinde, eklendiğinde, silindiğinde, depoda bazı boşluklar görünecek ve mümkünse daha sonra satırlar yerleştirilecektir. Ancak, TOP'u seçtiğimizde sıklıkla gördüğümüz şey, sıralı veriler olarak görünür , çünkü tablonun varlığının başlarında eklenmiş olabilir. Tabloda çok fazla silinme görülmezse , sıralı görünebilir . (örneğin, oluşturma tarihleri, tablonun oluşturulmasının kendisi kadar geçmiş olabilir). Ancak gerçek şu ki, eğer bu çok fazla silinen bir tabloysa, TOP N satırları hiç böyle görünmeyebilir.
Yani - buradaki sonuç (kelime anlamı), BOTTOM N kayıtlarını isteyen birinin aslında ne istediğini bilmediğidir. Ya da en azından ne istedikleri ve BOTTOM'un gerçekte ne anlama geldiği aynı şey değil.
Yani - çözüm, talepte bulunan kişinin gerçek iş ihtiyacını karşılayabilir ... ancak ALT olmak için kriterleri karşılamıyor.
insert
Satırları dizine eklenmemiş büyük bir tabloya koymak için büyük bir açıklama yaptım . (Tabloyu indekslemeye başlamadan önce dolduruyorum.) Müşteri oturumumu bir yeniden başlatma veya herhangi bir nedenle kaybettim ve şimdi yeni eklenen satırlarımın orada olup olmadığını görmek istiyorum. Tablonun 'alt' satırı en son satırlarımdan biriyse, işlemin tamamlandığını biliyorum. Eğer 'alt' sıra başka bir şeyse, hiçbir garanti yok ve emin olmak için tüm tabloyu taramalıyım ... ama büyük olasılıkla, 'alt' satırını hızlıca kontrol ederek biraz zaman kazanabilirim. üst'.
Şu anda "Justin Ethier" tarafından kabul edilen cevap, "Koruyucu Bir" tarafından işaret edildiği gibi doğru bir cevap değil.
Görebildiğim kadarıyla, şu an için başka hiçbir yanıt veya yorum, soru yazarının sorduğu BOTTOM (x) 'e eşdeğer değildir.
Öncelikle, bu işlevselliğin gerekli olacağı bir senaryo düşünelim:
SELECT * FROM Split('apple,orange,banana,apple,lime',',')
Bu, bir sütun ve beş kayıttan oluşan bir tablo döndürür:
Gördüğünüz gibi: bir kimlik sütunumuz yok; döndürülen sütuna göre sıralayamayız; ve ilk iki kayıt için yaptığımız gibi standart SQL kullanarak alttaki iki kaydı seçemiyoruz.
İşte bir çözüm sunma girişimim:
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
Ve işte daha eksiksiz bir çözüm:
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
Hiçbir şekilde bunun her koşulda kullanılmasının iyi bir fikir olduğunu iddia etmiyorum, ancak istenen sonuçları sağlıyor.
Yapmanız gereken tek şey, kendi ORDER BY
. Ekleyin veya kaldırın DESC
.
Diğer şekilde sıralamanın sorunu, genellikle endeksleri iyi kullanmamasıdır. Ayrıca, başında veya sonunda olmayan birkaç satır seçmeniz gerekirse, çok da genişletilemez. Alternatif bir yol aşağıdaki gibidir.
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;
Yukarıdaki "Tom H" yanıtı doğru ve Alt 5 satırları almakta benim için çalışıyor.
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
Teşekkürler.
bunu dene.
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
Buna, geri dönen satır sayısını bilmenizi gerektirmeyen bir çözüm buldum.
Örneğin, en son 1 (veya 2 veya 5 veya 34) dışındaki tüm konumların bir tabloda oturum açmasını istiyorsanız
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
SELECT TOP 10*from TABLE1 ORDER BY ID DESC
Kimlik, TABLO1'in birincil anahtarıdır.
İlk olarak, aşağıdakileri kullanarak tablonun orijinal sırasına göre bir alt sorguda bir dizin oluşturun:
ROW_NUMBER () OVER (ORDER BY (SELECT NULL) ) AS RowIndex
Ardından tabloyu RowIndex
, ana sorguda oluşturduğunuz sütuna göre azalan şekilde sıralayın :
ORDER BY RowIndex DESC
Ve son olarak TOP
istediğiniz sayıda satırla kullanın:
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