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

È stato utile?

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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top