5

我希望數據庫查詢的結果集具有特定的順序。我想要訂購的信息不包含在數據庫中,但是在代碼中動態生成(所以我不能使用ORDER BY)。執行查詢後爲數據集自定義排序順序?

有沒有辦法對執行數據庫查詢後對數據集進行排序? (我不需要索引訪問,但只想迭代所有記錄。)

+0

您正在使用什麼類型的數據集? – Linas

+0

@Linas TAdsQuery –

+0

您要用來訂購的列是計算的嗎? (使用OnCalcFields) – Cesar

回答

2

有可能與Jens的回答(+1)有相似之處,但以稍微不同的方式得出結果。

鑑於現有的表:

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

如果您知道所需的空頭排列(無論是通過處理表或從它的一些查詢結果),創建具有一些關鍵的值以匹配所需的臨時表從原始錶行,然後排序順序數據:

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

在臨時表設置sortvalue字段含有所需順序(它可以是任何可排序的數據類型 - 不必是整數):

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

然後產生一個對一起提供的排序順序表中的結果:

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

+1如果您有一個可以使用的唯一密鑰,這是一個好主意。 –

+0

我最喜歡大數據集,因爲要傳輸的數據量似乎最少。對於小數據集,我可能會選擇其中一種CDS解決方案。 –

2

AFAIK排序數據集的唯一可靠方法是使用ORDER BY

我想:

  1. 虛擬order_tag字段添加到您的查詢。
  2. 將結果轉儲到臨時表。
  3. 聲明一個遊標來遍歷臨時表並使用您的自定義邏輯和UPDATE #temp_table語句設置order_tag
  4. 從臨時表中選擇數據並按標記字段排序。
+0

這就是服務器端,當然你也可以在客戶端重新排序,就像其他一些答案建議的一樣。 –

+0

+1我喜歡這個想法,因爲我不想一次將所有數據傳輸到CDS。 Mark的答案更進一步,不將所有數據都複製到臨時表中。 –

3

隨着ClientDataSet的你能夠執行後更改順序。 設置IndexFieldNames對數據集進行排序。

可以找到信息here如何將clientdataset連接到同一應用程序中的另一個數據集。

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

好主意,但是這會將我所有的數據複製到CDS。所以它是小數據集的一種選擇。 –

1

主要的竅門在這裏將使用內部計算字段(FieldKind = fkInternalCalc),如果他們是由你TDataSet的子類支持。如果不是,請使用TClientDataset作爲中間值。

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;