需要一个好的方法使用Delphi在平面表中“旋转”(数据?)数据

时间:2012-03-28 02:04:43

标签: database delphi pivot

我有一个数据表,其记录具有重复的字段“位置” - 想象一个旋转表,其中有4个位置,每个位置编号为1到4 inc。我为每个旋转存储4个数据库表行,每行包含旋转位置1到4 inc,所以这个位置字段为1,2,3,4,1,2,3,4,1,2等。是:

Position  Field1 Field2 Field3
------------------------------
1         4.5    4.6    1.4 
2         5.5    3.6    2.4
3         4.5    7.6    3.4
4         7.5    2.6    4.4
1         2.5    3.6    5.4
2         3.5    9.6    6.4
3         9.5    3.6    7.4
4         1.5    6.6    8.4
1         2.5    9.6    9.4

我想显示一个网格(或生成一个表),其顶部(列)的位置字段1,2,3,4和我的其他每个原始数据字段(即列)行。从上面的例子可以看出:

        1        2        3        4
        ------------------------------
Field1  2.5      3.5      9.5      1.5
Field2  9.6      9.6      3.6      6.6
Field3  9.4      6.4      7.4      8.4

我要求只显示最后4个数据条目,我相信这是一种支点?我有Developer Express的Quantum Grid,所以我可以根据需要轻松添加他们的枢轴套件。我的要求是这应该非常快,只显示最后4个位置,而不是总和或其他聚合。我可以快速编码吗?这是报告工具可以做的事情吗?或者我应该使用枢轴套件解决方案吗?

1 个答案:

答案 0 :(得分:2)

这是我试图制定一个我认为很快的解决方案:

//
//  set alignment to 4 bytes, we will need it that way for later
//
{$A4}
type
  TMyRecord = record
    Position: Integer;
    Field1: Double;
    Field2: Double;
    Field3: Double;
  end;

const
  szMyRecord = SizeOf(TMyRecord);

const
  CMYRECORD_LIST: array[0..8] of TMyRecord = (
    (Position: 1; Field1: 4.5; Field2: 4.6; Field3: 1.4),
    (Position: 2; Field1: 5.5; Field2: 3.6; Field3: 2.4),
    (Position: 3; Field1: 4.5; Field2: 7.6; Field3: 3.4),
    (Position: 4; Field1: 7.5; Field2: 2.6; Field3: 4.4),
    (Position: 1; Field1: 2.5; Field2: 3.6; Field3: 5.4),
    (Position: 2; Field1: 3.5; Field2: 9.6; Field3: 6.4),
    (Position: 3; Field1: 9.5; Field2: 3.6; Field3: 7.4),
    (Position: 4; Field1: 1.5; Field2: 6.6; Field3: 8.4),
    (Position: 1; Field1: 2.5; Field2: 9.6; Field3: 9.4)
  );

const
  CDELTA = 4; // last 4 records
  CCOLUMNS = 4; // columns for target grid

procedure|function...
type
  //
  //  used for accessing our record Fields from 1 to 3 as array
  //
  TMyRecordHack = array[0..2] of Double;

const
  szInteger = SizeOf(Integer);

var
  Index: Integer;
  kIndex: Integer;
  LStartIndex: Integer;
  LRecFields: TMyRecordHack;
  LRecAddr: Integer;
  LMyListAddr: Integer;
  LCol: Integer;
  LRow: Integer;
begin
  LStartIndex := Length(CMYRECORD_LIST) - CDELTA;
  //
  //  store address of first record
  //
  LMyListAddr := Integer(@CMYRECORD_LIST[Low(CMYRECORD_LIST)]);
  //
  //  store the address of TMyRecord at LStartIndex
  //
  LRecAddr :=
    //
    //  CMYRECORD_LIST base address
    //
    LMyListAddr +
    //
    //  record address is RecordIndex * szMyRecord
    //
    LStartIndex * szMyRecord +
    //
    //  skip Position member of TMyRecord
    //
    szInteger;
  for Index := LStartIndex to High(CMYRECORD_LIST) do begin
    //
    //  convert address into pointer and cast pointer as TMyRecordHack
    //
    LRecFields := TMyRecordHack( Ptr( LRecAddr )^ );
    LCol := CMYRECORD_LIST[ Index ].Position;
    for kIndex := Low(LRecFields) to High(LRecFields) do begin
      //
      //  +1 required, we're using a string grid
      //
      LRow := kIndex +1;
      //
      //  display data
      //
      StringGrid1.Cells[ LCol, LRow ] := FloatToStr( LRecFields[ kIndex ] );
    end; // for kIndex := Low(LRecFields) to High(LRecFields) do begin
    //
    //  increment LRecAddr by szMyRecord
    //
    Inc(LRecAddr, szMyRecord);
  end; // for Index := LStartIndex to High(CMYRECORD_LIST) do begin
end;

好的,TMyRecordHack可能不是最好的名字,但你可以随意调用它(: