【问题标题】:get the amount from a price period table从价格周期表中获取金额
【发布时间】:2012-02-27 09:05:50
【问题描述】:

我有一个表价格周期 tblPricePeriod,其中我有 Amount 在特定公寓的两个日期之间收取费用。

我还有StartDateEndDate 列的价格时段,ApartmentId

下面是我的表结构:

现在我要计算收取预订天数的总金额。

例如,如果某人从 2 月 4 日到 2 月 7 日逗留,那么他必须按照以下方案付款:

4-     10
5-     10
6-     10  
7    -     nothing as this is checkout date 
-----------------------------------------------------
totamt--- 30$

我有startdateenddateapartmentid 作为参数,我使用的是ms access db。

现在我正在使用 c# 代码通过后续代码遍历它,但没有成功。

我一一获取所有日期的金额并将它们添加到一个全局变量中。

代码如下:

decimal amount = 0;

// loop to traverse all days between start date and end date 
for (DateTime d = Convert.ToDateTime(StartDate); d < Convert.ToDateTime(EndDate); d = d.AddDays(1))
{
    string priceCalc = "select Amount from tblPricePeriod where ApartmentId=" + ApartmenId + " and cdate(StartDate) <='" + d.ToShortDateString() + "' and cdate(EndDate) >= '" + d.ToShortDateString() + "'";
    DataSet dsPriceCalc = SqlHelper.ExecuteDataset(Connection.ConnectionString, CommandType.Text, priceCalc);
    if (dsPriceCalc.Tables[0].Rows.Count > 0)
    {
        amount = amount + Convert.ToDecimal(dsPriceCalc.Tables[0].Rows[0]["Amount"]);
    }
}

【问题讨论】:

  • 我不明白问题是什么?你得到一个错误或错误的总和?此外,如果您不希望客户在结帐日期付款,那么您应该在结帐日期使用&gt; 而不是&gt;=
  • 错误的模拟没有来自查询的数据并且数量保持为零
  • 那些 'StartDate' 和 'EndDate' 列,它们有 'date' 类型吗? Access 不需要“#”作为日期分隔符吗?
  • 能否尝试定位问题? priceCalcdsPriceCalcamount 是否包含任何数据?
  • 是的,他们有数据,因为我尝试使用调试器进行快速查看

标签: c# sql winforms ms-access


【解决方案1】:

这里是Sql中SUM函数的一个例子:

SELECT SUM(salary) as "Total Salary"
FROM employees
WHERE salary > 25000;

//编辑:

您可以直接选择金额的总和,而不是循环您的日期时间:

DateTime dtStartDate = Convert.ToDateTime(StartDate);
DateTime dtEndDate = Convert.ToDateTime(EndDate); // maybe -1 day 

string priceCalc = "select SUM( Amount ) from tblPricePeriod where ApartmentId=" + ApartmenId + " and cdate(StartDate) <= '" + dtStartDate.ToShortDateString( ) + "' and cDate(EndDate) >= '" + dtEndDate.ToShortDateString( ) + "'";

【讨论】:

  • @Viper Thit 如果有多个带有 startDate/EndDate 的记录是正确的,那么它将获取所有记录。
【解决方案2】:

您可以采用完全 SQL 的方法:

SELECT  SUM(TotalAmount) AS Amount
FROM    (   SELECT  Amount * (1 + DATEDIFF('d', @StartDate, EndDate))  AS TotalAmount,  
                    (1 + DATEDIFF('d', @StartDate, EndDate)) AS Days, 
                    Amount AS DailyRate
            FROM    tblPricePeriod
            WHERE   @StartDate >= StartDate
            AND     @StartDate <= EndDate
            AND     @EndDate > EndDate
            AND     ApartmentID = @ApartmentID
            UNION ALL
            SELECT  Amount * (DATEDIFF('d', @StartDate, @EndDate)),  DATEDIFF('d', @StartDate, @EndDate), Amount
            FROM    tblPricePeriod
            WHERE   @StartDate >= StartDate
            AND     @StartDate <= EndDate
            AND     @EndDate >= StartDate
            AND     @EndDate <= EndDate
            AND     ApartmentID = @ApartmentID
            UNION ALL
            SELECT  Amount * (1 + DATEDIFF('d', StartDate, EndDate)),  (1 + DATEDIFF('d', StartDate, EndDate)) , Amount
            FROM    tblPricePeriod
            WHERE   @StartDate < StartDate
            AND     @EndDate > EndDate
            AND     ApartmentID = @ApartmentID
            UNION ALL
            SELECT  Amount * (DATEDIFF('d', StartDate, @EndDate)),  DATEDIFF('d', StartDate, @EndDate) , Amount
            FROM    tblPricePeriod
            WHERE   @StartDate < StartDate
            AND     @EndDate <= EndDate
            AND     @EndDate > StartDate
            AND     ApartmentID = @ApartmentID
        ) AS Data

由于 Access 不允许 cmets,我无法对查询进行注释。子查询有 4 个部分,顶部是访问期间价格周期结束日期发生的时间,第二个是访问完全在 1 个价格周期内时,第三个是访问跨越整个价格周期时,第四个是访问期间价格周期开始的时间。希望这很清楚。

然后您需要做的就是将参数@ApartmentID、@StartDate 和@EndDate 添加到您的ExecuteDataset 方法中,这无论如何都是比连接字符串更好的方法。

【讨论】:

    【解决方案3】:
    SELECT
      SUM(( 
        IIF(EndDate < @EndDate, EndDate, IIF(@EndDate < StartDate, StartDate, @EndDate)) -
        IIF(StartDate > @StartDate, StartDate, IIF(@StartDate > EndDate, EndDate, @StartDate))
      ) * Amount)
    FROM tblPricePeriod 
    

    这采用与 GarethD 相同的方法。它当然更短,但你可以争辩说哪个更清楚地显示了意图。我无法对此进行测试,因为我无权访问,但我相信它具有 IIF 语句。 @EndDate 参数需要是您的结束日期 - 1。所以在您的示例中,我将通过 @End Date = 2 月 6 日。

    IIF语句基本上是计算每个周期内需要统计的天数。

    【讨论】:

    • 这也是我的第一个想法,但由于某种原因 Access 返回“此表达式键入错误,或者它太复杂而无法评估。例如,一个数值表达式可能包含太多复杂的元素。尝试通过将表达式的部分分配给变量来简化表达式”。但是,如果您将 @StartDate 替换为实际日期(#27/02/2012#),它运行良好。我无法弄清楚这一点,所以我采用了联合方法,因为我能够让它发挥作用。
    猜你喜欢
    • 2018-04-22
    • 1970-01-01
    • 2020-05-03
    • 2016-12-28
    • 1970-01-01
    • 2016-03-26
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多