5

Quiero que el conjunto de resultados de una consulta de base de datos tenga un cierto orden. La información que deseo ordenar no está contenida en la base de datos, sino que se genera dinámicamente en el código (por lo que no puedo usar ORDER BY).Orden de clasificación personalizado para el conjunto de datos después de ejecutar la consulta?

¿Hay alguna manera de ordenar un conjunto de datos después de ejecutando la consulta de la base de datos? (No necesito acceso indexado, pero solo quiero iterar sobre todos los registros)

+0

¿Qué tipo de conjunto de datos está utilizando? – Linas

+0

@Linas TAdsQuery –

+0

¿Se calcula la columna que desea utilizar para realizar el pedido? (usando OnCalcFields) – Cesar

Respuesta

2

Existe la posibilidad de que comparta similitudes con la respuesta de Jens (+1) pero llega al resultado de una manera ligeramente diferente.

Dada una tabla existente:

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'); 

Si conoce el poco tiempo deseado (ya sea mediante el procesamiento de la mesa o algún resultado de la consulta de ella), cree una tabla temporal que tiene algún valor clave para que coincida con la deseada filas de la tabla original y luego el orden de clasificación de datos:

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

Configure el campo sortvalue en la tabla temporal para contener el orden deseado (que podría ser cualquier tipo de datos sortable - no tiene que ser un número entero):

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

luego generar los resultados con una unión en contra de la tabla que proporciona el orden de clasificación:

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

+1 Esta es una buena idea si tiene una clave única que puede usar. –

+0

Esto me gusta más para conjuntos de datos grandes, porque la cantidad de datos para transferir parece ser la menor. Para conjuntos de datos pequeños, probablemente optaría por una de las soluciones CDS. –

2

AFAIK la única forma confiable de ordenar un conjunto de datos es usar ORDER BY.

lo haría:

  1. Añadir un campo ficticio order_tag a su consulta.
  2. Vuelque los resultados en la tabla temporal.
  3. Declare un cursor para iterar sobre la tabla temporal y configure order_tag usando su lógica personalizada y declaraciones UPDATE #temp_table.
  4. Seleccione los datos de la tabla temporal y ordene por el campo de etiqueta.
+0

Eso está en el lado del servidor, por supuesto, puede reordenar en el lado del cliente también, como sugieren algunas de las otras respuestas. –

+0

+1 Me gusta la idea porque no quiero transferir todos los datos a la vez a un CDS. La respuesta de Mark va un paso más allá al no copiar todos los datos en una tabla temporal. –

3

Con un ClientDataset que son capaces de cambiar el orden después de la ejecución. Configuración IndexFieldNames ordena el conjunto de datos.

Puede encontrar información here cómo conectar un conjunto de datos de cliente a otro conjunto de datos en la misma aplicación.

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

Buena idea, pero esto copiaría todos mis datos en el CDS. Por lo tanto, es una opción para pequeños conjuntos de datos. –

1

El truco principal aquí sería el uso de un campo Calc interna (FieldKind = fkInternalCalc) si son compatibles con el TDataset subclase. Si no lo son, use un TClientDataset como intermediario.

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; 
Cuestiones relacionadas