在sql查询中组合来自先前和当前记录的数据

时间:2016-02-15 14:35:15

标签: delphi

让我举个例子来解释一下。我有下表:

1.    2010    100     
2.    2011    200
3.    2012    150
4.    2013    300

我需要有如下结果集:

1.    2010    100    200
2.    2011    200    150
3.    2012    150    300
4.    2013    300    500

如您所见,结果应该有第二列,该值是以下记录的第一列。我在Delphi和BDE工作,因此使用本地SQL。

我没有办法做到这一点。如果这不能在本地SQL中完成,我想知道这是否可以在SQLite中完成

2 个答案:

答案 0 :(得分:2)

以下适用于MS Sql Server

select
  t1.id,
  t1.year,
  t1.amount,
  coalesce((select amount from table_1 t2 where t2.year = t1.year + 1), 0) as nextyearamount
from
  table_1 t1
order by
  t1.year

id          year        amount      nextyearamount
----------- ----------- ----------- --------------
1           2010        100         200
1           2011        200         150
1           2012        150         300
1           2013        300         0

所以我希望它或类似于在Sqlite中工作的东西。它是否在BDE中工作是另一回事 - 我对它的回忆是,除了简单的SELECT之外,它还是相当悲惨的。试试吧,看看。

不过,这是设计选择的问题,你在最近一年的第四栏中做了什么,nextyearamount, - 我把它设置为零。如果2014年的金额当然是那么2013年只有500。

如果您希望在代码而不是Sql中执行此操作,并且您使用的是TClientDataSet或支持fkInternalCalc字段的其他数据集类型(对于NextYearAmount字段),您可以这样做:

procedure TForm1.FormCreate(Sender: TObject);
var
  NextYearAmount : Variant;
begin
  VarClear(NextYearAmount);
  CDS1.Open;  //  NB must be ordered by the Year field
  CDS1.Last;
  while not CDS1.Bof do begin
    if NextYearAmount <> UnAssigned then begin
      CDS1.Edit;
      CDS1.FieldByName('NextYearAmount').Value := NextYearAmount;
      CDS1.Post;
    end;
    NextYearAmount := CDS1.FieldByName('Amount').Value;
    CDS1.Prior;
  end;
end;

答案 1 :(得分:0)

没有必要折磨sql - 添加计算列,运行数据集并使用所需值初始化它。向后运行并不常见,因此我没有检查这种方法:

PriorValue := 0;

with MyDataset do
begin
  Last;
  PriorValue := <dataset>.FieldValue['MyValue_Col_1'];
  // Note: you have to do something with the very last row;
  Prior;

  while not BOF do
  begin
    Edit;
    FieldValues['MyValue_Col_2'] := PriorValue;
    PriorValue := FieldValues['MyValue_Col_1'];
    Prior;
  end;
end;

更好的解决方案是将其倒置并循环前进(FirstNextEOF)。