L'ultimo elemento in una tabella SQL
-
09-06-2019 - |
Domanda
Ho una Tabella in SQL Server che fondamentalmente tracce di un elemento attraverso un processo.La voce ha alcuni campi fissi che non cambiano durante tutto il processo, ma ha un paio di altri campi tra stato e di identità, che incrementa i passaggi del processo di aumento.
Fondamentalmente voglio recuperare l'ultimo passaggio per ogni elemento dato un Lotto di Riferimento.Quindi se faccio un
Select * from HistoryTable where BatchRef = @BatchRef
Restituirà tutti i passaggi per tutti gli elementi in batch - eg
Stato Id BatchRef ItemCount 1 1 Batch001 100 1 2 Batch001 110 2 1 Batch001 60 2 2 Batch001 100
Ma quello che voglio veramente è:
Stato Id BatchRef ItemCount 1 2 Batch001 110 2 2 Batch001 100
Edit:Scuse - non riesco a ottenere i tag di TABELLA di lavorare con Markdown - seguito la guida alla lettera, e guarda bene in anteprima
Soluzione
E ' difficile dare un senso ai tuoi tavolo design - credo di sì mangiato la tua delimitatori.
Il modo di base di gestione di questo è per il GRUPPO DA fisso campi e selezionare un MAX (o MIN) per alcuni unqiue valore (data e ora di solito funziona bene).Nel tuo caso, io pensare che il GRUPPO sarebbe BatchRef e ItemCount, e l'Id sarà la vostra unica colonna.
Quindi, iscriversi nuovamente al tavolo per ottenere tutte le colonne.Qualcosa di simile a:
SELECT *
FROM HistoryTable
JOIN (
SELECT
MAX(Id) as Id.
BatchRef,
ItemCount
FROM HsitoryTable
WHERE
BacthRef = @batchRef
GROUP BY
BatchRef,
ItemCount
) as Latest ON
HistoryTable.Id = Latest.Id
Altri suggerimenti
Supponendo che si dispone di una colonna di identità in tavola...
select
top 1 <fields>
from
HistoryTable
where
BatchRef = @BatchRef
order by
<IdentityColumn> DESC
Supponendo che l'Articolo Id sono numerate in modo incrementale:
--Declare a temp table to hold the last step for each item id
DECLARE @LastStepForEach TABLE (
Id int,
Status int,
BatchRef char(10),
ItemCount int)
--Loop counter
DECLARE @count INT;
SET @count = 0;
--Loop through all of the items
WHILE (@count < (SELECT MAX(Id) FROM HistoryTable WHERE BatchRef = @BatchRef))
BEGIN
SET @count = @count + 1;
INSERT INTO @LastStepForEach (Id, Status, BatchRef, ItemCount)
SELECT Id, Status, BatchRef, ItemCount
FROM HistoryTable
WHERE BatchRef = @BatchRef
AND Id = @count
AND Status =
(
SELECT MAX(Status)
FROM HistoryTable
WHERE BatchRef = @BatchRef
AND Id = @count
)
END
SELECT *
FROM @LastStepForEach
SELECT id, status, BatchRef, MAX(itemcount) AS maxItemcount
FROM HistoryTable GROUP BY id, status, BatchRef
HAVING status > 1
E 'un po' difficile decripta i vostri dati in modo WMD ha formattato, ma si può tirare il tipo di trucco è necessario con espressioni di tabella comuni su SQL 2005:
with LastBatches as (
select Batch, max(Id)
from HistoryTable
group by Batch
)
select *
from HistoryTable h
join LastBatches b on b.Batch = h.Batch and b.Id = h.Id
O una sottoquery (supponendo che il gruppo nella sottoquery opere - largo della parte superiore della mia testa, io non ricordo):
select *
from HistoryTable h
join (
select Batch, max(Id)
from HistoryTable
group by Batch
) b on b.Batch = h.Batch and b.Id = h.Id
Edit:Stavo ipotizzando di aver voluto l'ultimo elemento per ogni batch.Se è necessario solo per il lotto poi le altre risposte (che fa un top 1 e ordine decrescente) sono il modo migliore per andare.
Come già suggerito, probabilmente si vorrà per riordinare le query per ordinare in un'altra direzione, quindi in effetti il fetch della prima riga.Allora si sarebbe probabilmente desidera utilizzare qualcosa di simile
SELECT TOP 1 ...
se si utilizza MSSQL 2k o precedente, o in SQL compatibile variante
SELECT * FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY key ASC) AS rownumber,
columns
FROM tablename
) AS foo
WHERE rownumber = n
per qualsiasi altra versione (o di altri sistemi di database che supportano la notazione standard), o
SELECT ... LIMIT 1 OFFSET 0
per altre varianti senza SQL standard di supporto.
Vedi anche questo domanda per ulteriori discussioni in giro per la selezione di righe.Utilizzando la funzione di aggregazione max() potrebbe o non potrebbe essere più veloce a seconda che il calcolo del valore richiede una scansione della tabella.