5

Desidero che il set di risultati di una query di database abbia un determinato ordine. Le informazioni che voglio ordinare non sono contenute nel database, ma generate dinamicamente nel codice (quindi non posso usare ORDER BY).Ordinamento personalizzato per set di dati dopo l'esecuzione della query?

C'è un modo per ordinare un set di dati dopo esecuzione della query del database? (Non ho bisogno di accesso indicizzato ma voglio solo scorrere su tutti i record.)

+0

Che tipo di set di dati stai usando? – Linas

+0

@Linas TAdsQuery –

+0

La colonna che si desidera utilizzare per l'ordine viene calcolata? (utilizzando OnCalcFields) – Cesar

risposta

2

C'è una possibilità che condivide somiglianze con la risposta di Jens (+1) ma arriva al risultato in modo leggermente diverso.

Data una tabella esistente:

create table somedata (id integer, name char(20)); 
insert into somedata values (1, 'Tim'); 
insert into somedata values (2, 'Bob'); 
insert into somedata values (3, 'Joe'); 

Se si conosce il breve tempo desiderato (sia per l'elaborazione della tabella o qualche risultato di una query da esso), creare una tabella temporanea che ha un certo valore chiave per abbinare il desiderato righe della tabella originale e quindi i dati di ordinamento:

create table #sortorder(id integer, sortvalue integer); 

Impostare il campo sortvalue nella tabella temporanea per contenere l'ordine desiderato (potrebbe essere qualsiasi tipo di dati sortable - non deve essere un numero intero):

insert into #sortorder values (1, 15); 
insert into #sortorder values (2, 12); 
insert into #sortorder values (3, 5); 

quindi generare il risultato con un join contro il tavolo che fornisce il criterio di ordinamento:

select sd.* from somedata sd, #sortorder so 
     where sd.id = so.id 
     order by so.sortvalue; 
+0

+1 Questa è una buona idea se si dispone di una chiave univoca che è possibile utilizzare. –

+0

Mi piace di più per i dataset di grandi dimensioni, perché la quantità di dati da trasferire sembra il minimo. Probabilmente per i set di dati di piccole dimensioni probabilmente opterei per una delle soluzioni CDS. –

2

AFAIK l'unico modo affidabile per ordinare un set di dati è utilizzare ORDER BY.

lo farei:

  1. Aggiungi un manichino order_tag campo alla tua richiesta.
  2. Scarica i risultati nella tabella temporanea.
  3. Dichiarare un cursore per scorrere sulla tabella temporanea e impostare order_tag utilizzando la logica personalizzata e le dichiarazioni UPDATE #temp_table.
  4. Selezionare i dati dalla tabella temporanea e ordinare dal campo del tag.
+0

Che si trova sul lato server, è ovviamente possibile riordinare anche dal lato client, come suggeriscono alcune delle altre risposte. –

+0

+1 Mi piace l'idea perché non desidero trasferire tutti i dati contemporaneamente su un CDS. La risposta di Mark fa un passo avanti non copiando tutti i dati su una tabella temporanea. –

3

Con un ClientDataSet si è in grado di cambiare l'ordine dopo l'esecuzione. Impostazioni IndexFieldNames ordina il set di dati.

È possibile trovare informazioni here come connettere un set di dati client a un altro set di dati nella stessa applicazione.

object DataSetProvider1: TDataSetProvider 
    DataSet = MyAdsQuery 
    Left = 208 
    Top = 88 
    end 
    object ClientDataSet1: TClientDataSet 
    Aggregates = <> 
    Params = <> 
    ProviderName = 'DataSetProvider1' 
    Left = 296 
    Top = 88 
    end 
+0

Buona idea, ma questo coperebbe tutti i miei dati sul CDS. Quindi è un'opzione per piccoli set di dati. –

1

Il trucco principale qui sarebbe quella di utilizzare un campo di calc interno (FieldKind = fkInternalCalc) se sono supportati dal proprio TDataset sottoclasse. In caso contrario, utilizzare un TClientDataset come intermedio.

DFM:

object ClientDataSet1SortField: TIntegerField 
    FieldKind = fkInternalCalc 
    FieldName = 'SortField' 
end 

pas:

procedure TForm1.FormCreate(Sender: TObject); 
begin 
    ADOConnection1.Open('dbuser', 'Hunter2'); 
    ClientDataSet1.SetProvider(ADOQuery1); // set ClientDataset provider. This will create a TLocalAppServer provider "in the background" 
    ClientDataSet1.Open; 
    randomize; 
    while not ClientDataSet1.Eof do 
    begin 
    ClientDataSet1.edit; 

    ClientDataSet1SortField.AsInteger := random(100); 
    // as ClientDataSet1SortField is fkInternalCalc it doesn't need to be in the query result set, but can be assigned and used for sorting 
    ClientDataSet1.Post; 
    ClientDataSet1.Next; 
    end; 
    clientdataset1.IndexFieldNames := 'SortField'; 
end; 
Problemi correlati