酒店价格跨越多个日期问题

时间:2013-04-08 15:34:22

标签: sql delphi delphi-xe2 delphi-xe

问题在某种程度上与这个问题有关,除了我使用参数。 我点击了我的按钮:

procedure TForm1.Button1Click(Sender: TObject);
begin
with ABSQuery1 do begin
ABSQuery1.Close;
ABSQuery1.SQL.Clear;
ABSQuery1.SQL.Add('select * from ROOM_RATES where CENIK_ID = :a4 and ROOM_TYPE = :A1');
ABSQuery1.SQL.Add('and rate_Start_DATE < :a3 AND rate_End_DATE  > :a2 ORDER BY rate_Start_DATE ASC ');
ABSQuery1.Params.ParamByName('a1').Value:= cxLookupComboBox2.Text;
ABSQuery1.Params.ParamByName('a2').Value:= cxDateEdit1.Date;
ABSQuery1.Params.ParamByName('a3').Value := cxDateEdit2.Date;
ABSQuery1.Params.ParamByName('a4').Value := cxLookupComboBox1.Text;
ABSQuery1.Open;
end;
end;

这种作品但不是我想要的。问题与这个问题有关: Hotel Booking Rates SQL Problem

问题在于重叠的日期,就像上面提到的超链接一样。现在我得到这个:

如何通过上述示例获得与上述超链接类似的结果?

这是db表的快照: enter image description here

更新(新): 这是按钮点击的代码:

procedure TForm1.AdvGlowButton1Click(Sender: TObject);
var
     nxt             : integer;
     mem_from         : TDateTime;
     mem_to           : TDateTime;
     mem_RATE_ID      : integer;
     mem_ROOM_TYPE    : string[10];
     mem_Start_DATE_1 : TDateTime;
     mem_End_DATE_1   : TDateTime;
     mem_RATE_Price_1 : Currency;
     mem_calc_END     : TDateTime;
     mem_calc_DAYS    : integer;
     c_from           : TDateTime;
     c_to             : TDateTime;
     c_from_test      : TDateTime;
     c_to_test        : TDateTime;

begin
ABSQuery2.Close;
ABSQuery2.SQL.Text:='DELETE from TEMP';
ABSQuery2.ExecSQL;
ABSQuery2.SQL.Text:='SELECT * from TEMP ORDER BY ID ';
ABSQuery2.Open;

c_from := cxDateEdit1.Date;
c_to   := cxDateEdit2.Date;

mem_from := cxDateEdit1.Date;
mem_to   := cxDateEdit2.Date;

with ABSQuery1 do begin
ABSQuery1.Close;
ABSQuery1.SQL.Clear;
ABSQuery1.SQL.Add('select * from ROOM_RATES where CENIK_ID = :a4 and ROOM_TYPE = :A1');
ABSQuery1.SQL.Add('and rate_Start_DATE < :a3 AND rate_End_DATE  > :a2 ORDER BY rate_Start_DATE ASC ');
ABSQuery1.Params.ParamByName('a1').Value:= cxLookupComboBox2.Text;
ABSQuery1.Params.ParamByName('a2').Value:= cxDateEdit1.Date;
ABSQuery1.Params.ParamByName('a3').Value := cxDateEdit2.Date;
ABSQuery1.Params.ParamByName('a4').Value := cxLookupComboBox1.Text;
ABSQuery1.Open;

     nxt              := 1;
     mem_RATE_ID      := ABSQuery1.FieldByName('RATE_ID').AsInteger;
     mem_ROOM_TYPE    := ABSQuery1.FieldByName('ROOM_TYPE').AsString ;
     mem_Start_DATE_1 := ABSQuery1.FieldByName('RATE_START_DATE').AsDateTime;
     mem_End_DATE_1   := ABSQuery1.FieldByName('RATE_END_DATE').AsDateTime;
     mem_RATE_Price_1 := ABSQuery1.FieldByName('RATE_PRICE').AsCurrency;

     if mem_to > mem_End_DATE_1 then begin
         mem_calc_END  := mem_End_DATE_1;
         mem_calc_DAYS := Daysbetween(mem_from,mem_End_DATE_1);
     end else begin
         mem_calc_END  := mem_to;
         mem_calc_DAYS := Daysbetween(mem_from,mem_calc_END);
     end;
end;

if ABSQuery1.RecordCount > nxt then ABSQuery1.Next;
with ABSQuery2 do begin
open;
Insert;
  ABSQuery2.FieldByName('RATE_ID').AsInteger:=mem_RATE_ID;
  ABSQuery2.FieldByName('ROOM_TYPE').AsString:=mem_ROOM_TYPE;
  ABSQuery2.FieldByName('DATE_FROM').AsDateTime:=mem_from;
  ABSQuery2.FieldByName('DATE_TO').AsDateTime:= mem_to;//mem_calc_END;
  ABSQuery2.FieldByName('RATE_PRICE').AsCurrency:=mem_RATE_PRICE_1;
  ABSQuery2.FieldByName('DAYS').AsInteger:=mem_calc_DAYS;
  ABSQuery2.FieldByName('TOTAL').AsCurrency:=mem_RATE_PRICE_1 * mem_calc_DAYS;
post;
end;  ///////////////////////////////////////////////////////////////////
if ABSQuery1.RecordCount > nxt then begin
     inc(nxt);

    if mem_to < ABSQuery1.FieldByName('rate_End_DATE').AsDateTime then begin
       mem_calc_END   := mem_to;
       mem_calc_DAYS  := Daysbetween(ABSQuery1.FieldByName('rate_Start_DATE').AsDateTime,mem_calc_END);
    end else begin
       mem_calc_END   := ABSQuery1.FieldByName('rate_End_DATE').AsDateTime;
       mem_calc_DAYS  := Daysbetween(ABSQuery1.FieldByName('rate_Start_DATE').AsDateTime, ABSQuery1.FieldByName('rate_End_DATE').AsDateTime);
    end;
       mem_RATE_ID      := ABSQuery1.FieldByName('RATE_ID').AsInteger;
       mem_ROOM_TYPE    := ABSQuery1.FieldByName('ROOM_TYPE').AsString;
       mem_Start_DATE_1 := ABSQuery1.FieldByName('rate_Start_DATE').AsDateTime;
       mem_End_DATE_1   := ABSQuery1.FieldByName('rate_End_DATE').AsDateTime;
       mem_Rate_Price_1 := ABSQuery1.FieldByName('RATE_PRICE').AsCurrency;

    // calculation : second row.
with ABSQuery2 do begin
Insert;
  FieldByName('RATE_ID').AsInteger:=mem_RATE_ID;
  FieldByName('ROOM_TYPE').AsString:=mem_ROOM_TYPE;
  FieldByName('DATE_FROM').AsDateTime:=mem_Start_DATE_1;
  FieldByName('DATE_TO').AsDateTime:= mem_calc_END;
  FieldByName('RATE_PRICE').AsCurrency:=mem_RATE_PRICE_1;
  FieldByName('DAYS').AsInteger:=mem_calc_DAYS;
  FieldByName('TOTAL').AsCurrency:=mem_RATE_PRICE_1 * mem_calc_DAYS;
post;
end;
 ABSQuery2.refresh;
end;
end;

我得到的结果是: enter image description here

从数据库快照中可以看出,价格设置正常。

1 个答案:

答案 0 :(得分:1)

使用Delphi 2010进行测试。

您唯一的一个DBGrid与dataset-table-pricelist

相关联

匹配两行dataset-table-pricelist,因此在你的ABSQuery1 DBGrid中 显示价目表中的第1行 显示价目表中的第3行。

现在对于两个行程序ABSQuery1CalcFields(DataSet: TDataSet);
用相同的值调用!!

Daysbetween(cxDateEdit1.Date,cxDateEdit2.Date) = allways 19

procedure TForm1.ABSQuery1CalcFields(DataSet: TDataSet);
begin
ABSQuery1.FieldByName('Days').Value := IntToStr(Daysbetween(cxDateEdit1.Date,cxDateEdit2.Date));
ABSQuery1.FieldByName('TOTAL').AsCurrency :=ABSQuery1.FieldByName('Days').Value * ABSQuery1.FieldByName('RATE_PRICE').Value ;
end;

因此,你在DBGrid中有两天是19 From和To这两个字段也来自表价格表 因此,您无法看到自己的数据From和To。

您应该有2个表

  • 价目表
  • 计算

在表格价格表上有一个循环,获取价目表所需的数据。

  • 清晰的计算。
  • 从表格价格表中插入数据。

enter image description here

因为我不确切知道你的表是如何设置的,所以你必须使代码适应数据库和你的表。

为了更好地展示必要的步骤,请在此处输入以下代码 更新:这里,现在是完整的代码。

unit PriceList;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, Grids, DBGrids, Db, ZAbstractRODataset, ZAbstractDataset,
  ZDataset, ZConnection;

type
  TForm1 = class(TForm)
    ZConnection1: TZConnection;
    ABSQuery1: TZQuery;
    calculation: TZQuery;
    DataSource1: TDataSource;
    DataSource2: TDataSource;
    DBGrid1: TDBGrid;
    DBGrid2: TDBGrid;
    DoCalc: TButton;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    Edit1: TEdit;
    Edit2: TEdit;
    Edit3: TEdit;
    Edit4: TEdit;
    RATE_ID: TLargeintField;
    CENIK_ID: TLargeintField;
    ROOM_TYPE: TWideStringField;
    RATE_START_DATE: TDateTimeField;
    RATE_END_DATE: TDateTimeField;
    RATE_PRICE: TFloatField;
    calculationID: TLargeintField;
    calcRATE_ID: TLargeintField;
    calcROOM_TYPE: TWideStringField;
    calcDFROM: TDateTimeField;
    calcDTO: TDateTimeField;
    calcRATE_PRICE: TFloatField;
    calcDAYS: TLargeintField;
    calcTOTAL: TFloatField;
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

uses DateUtils;

procedure TForm1.DoCalcClick(Sender: TObject);
var
     nxt             : integer;
     mem_from         : TDateTime;
     mem_to           : TDateTime;

     mem_RATE_ID      : integer;
     mem_ROOM_TYPE    : string[20];
     mem_Start_DATE_1 : TDateTime;
     mem_End_DATE_1   : TDateTime;
     mem_RATE_Price_1 : Currency;
     mem_calc_END     : TDateTime;
     mem_calc_DAYS    : integer;
     c_from           : string[19];
     c_to             : string[19];
     c_from_test      : string[19];
     c_to_test        : string[19];

begin
calculation.Close;
calculation.SQL.Text:='DELETE from calculation';
calculation.ExecSQL;
calculation.SQL.Text:='SELECT * from calculation ORDER BY ID ';
calculation.Open;

c_from := Edit3.Text;
c_to   := Edit4.Text;
c_from_test := copy(Edit3.Text,7,4)+'.'+copy(Edit3.Text,4,2)+'.'+copy(Edit3.Text,1,2); // From 01.01.2013
c_to_test   := copy(Edit4.Text,7,4)+'.'+copy(Edit4.Text,4,2)+'.'+copy(Edit4.Text,1,2);
mem_from         := StrToDateTime(c_from);
mem_to           := StrToDateTime(c_to);

with ABSQuery1 do begin
    Close;
    SQL.Clear;
    SQL.Add('select * from ROOM_RATES where CENIK_ID = "'+Edit1.Text+'" and ROOM_TYPE = "'+Edit2.Text+'"');
    SQL.Add('and RATE_START_DATE < '''+c_to_test+''' AND RATE_END_DATE  > '''+c_from_test+''' ORDER BY RATE_START_DATE ASC ');
    Open;
     nxt              := 1;
     mem_RATE_ID      := RATE_ID.AsLargeInt;
     mem_ROOM_TYPE    := ROOM_TYPE.AsString ;
     mem_Start_DATE_1 := RATE_START_DATE.AsDateTime;
     mem_End_DATE_1   := RATE_END_DATE.AsDateTime;
     mem_RATE_Price_1 := RATE_PRICE.AsCurrency;

     if mem_to > mem_End_DATE_1 then begin
         mem_calc_END  := mem_End_DATE_1;
         mem_calc_DAYS := Daysbetween(mem_from,mem_End_DATE_1);
     end else begin
         mem_calc_END  := mem_to;
         mem_calc_DAYS := Daysbetween(mem_from,mem_calc_END);
     end;

end;

if ABSQuery1.RecordCount > nxt then ABSQuery1.Next;

with calculation do begin
open;
Insert;
calculation.FieldByName('RATE_ID').AsInteger:=mem_RATE_ID;
calculation.FieldByName('ROOM_TYPE').AsString:=mem_ROOM_TYPE;
calculation.FieldByName('DFROM').AsDateTime:=mem_from;
calculation.FieldByName('DTO').AsDateTime:= mem_calc_END;
calculation.FieldByName('RATE_PRICE').AsCurrency:=mem_RATE_PRICE_1;
calculation.FieldByName('DAYS').AsInteger:=mem_calc_DAYS;
calculation.FieldByName('TOTAL').AsCurrency:=mem_RATE_PRICE_1 * mem_calc_DAYS;
post;
end;

if ABSQuery1.RecordCount > nxt then begin
     inc(nxt);
    if mem_to < rate_End_DATE.AsDateTime then begin
         mem_calc_END   := mem_to;
         mem_calc_DAYS  := Daysbetween(rate_Start_DATE.AsDateTime,mem_calc_END);
    end else begin
         mem_calc_END   := rate_End_DATE.AsDateTime;
         mem_calc_DAYS  := Daysbetween(rate_Start_DATE.AsDateTime, rate_End_DATE.AsDateTime);
    end;
         mem_RATE_ID      := RATE_ID.AsInteger;
         mem_ROOM_TYPE    := ROOM_TYPE.AsString;
         mem_Start_DATE_1 := rate_Start_DATE.AsDateTime;
         mem_End_DATE_1   := rate_End_DATE.AsDateTime;
         mem_Rate_Price_1 := RATE_PRICE.AsCurrency;

with calculation do begin
Insert;
FieldByName('RATE_ID').AsInteger:=mem_RATE_ID;
FieldByName('ROOM_TYPE').AsString:=mem_ROOM_TYPE;
FieldByName('DFROM').AsDateTime:=mem_Start_DATE_1;
FieldByName('DTO').AsDateTime:= mem_calc_END;
FieldByName('RATE_PRICE').AsCurrency:=mem_RATE_PRICE_1;
FieldByName('DAYS').AsInteger:=mem_calc_DAYS;
FieldByName('TOTAL').AsCurrency:=mem_RATE_PRICE_1 * mem_calc_DAYS;
post;
end;
end;
calculation.refresh;
end;

end.

时间限制代码未优化。只是为了展示必要的步骤。

room_rates

DROP TABLE IF EXISTS `room_rates`;
CREATE TABLE  `room_rates` (
  `ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `CENIK_ID` int(10) unsigned NOT NULL,
  `ROOM_TYPE` varchar(45) NOT NULL,
  `RATE_START_DATE` datetime NOT NULL,
  `RATE_END_DATE` datetime NOT NULL,
  `RATE_PRICE` decimal(5,2) NOT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

calculation

DROP TABLE IF EXISTS `calculation`;
CREATE TABLE  `calculation` (
  `ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `RATE_ID` int(10) unsigned NOT NULL,
  `ROOM_TYPE` varchar(45) NOT NULL,
  `DFROM` datetime NOT NULL,
  `DTO` datetime NOT NULL,
  `RATE_PRICE` decimal(5,2) NOT NULL,
  `DAYS` int(10) unsigned NOT NULL,
  `TOTAL` decimal(7,2) NOT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

更新:

搜索if mem_to > mem_End_DATE_1
要更改Total 0,00€您必须展开

     if mem_to > mem_End_DATE_1 then begin
         mem_calc_END  := mem_End_DATE_1;
         mem_calc_DAYS := Daysbetween(mem_from,mem_End_DATE_1);
     end else begin 
         mem_calc_END  := mem_to;
         mem_calc_DAYS := Daysbetween(mem_from,mem_calc_END);
     end;

更新2 :上面,现在是完整的代码。

更新3 but still I get from 14/4/2013 to 26/4/2013 11 DAYS ! user763539

此行为来自DaysBetween(..,..),而不是来自我的代码 DaysBetween是一个delphi函数!

我告诉你3次。

您是否检查了从cxDateEdit1.DatecxDateEdit2.Date获得的内容。

必须准确14-04-2013 00:00:0026-04-2013 00:00:00

创建一个新的测试程序。

控制你得到的东西。

DateTimeToString(formattedDateTime, 'c', cxDateEdit1.Date);
Memo1.Lines.Add(formattedDateTime);

循环显示所有ROOM_RATES records您还应该检查ROOM_RATES中的所有日期字段。

DateTimeToString(formattedDateTime, 'c', ABSQuery1.FieldByName('RATE_START_DATE').AsDateTime);
Memo1.Lines.Add(formattedDateTime);

所有时间应为00:00:00

例如:

DaysBetween .. 14-04-2013 12:15:10 and 26-04-2013 12:15:05 == 11天`

更准确:11 Days : 23 Hours : 59 minutes : 55 seconds