MySQL计算查询

时间:2017-08-07 15:40:09

标签: mysql vb.net

我有这个表,只有两列,每个记录存储给定月份的利率:

id     rate
===========
199502 3.63
199503 2.60
199504 4.26
199505 4.25
...    ...
201704 0.79
201705 0.93
201706 0.81
201707 0.80
201708 0.14

根据这个比率,我需要创建另一个累积费率表,其结构类似,其数据按YYYYMM(月/年)参数的函数计算,这种方式(此公式在法律上是强制性的):

  1. 作为参数给出的月份始终为0(零)
  2. 前一个月的比率始终为1(一)
  3. 前几个月'费率将是(一)加上给定月份与作为参数给出的月份之间的月份之和。
  4. 在给定参数201708的情况下,我将通过此示例澄清此规则:

    SOURCE         CALCULATED
    id     rate    id       rate
    ===========    =============
    199502 3.63    199502 360.97 (1 + sum(rate(199503) to rate(201707)))
    199503 2.60    199503 358.37 (1 + sum(rate(199504) to rate(201707)))
    199504 4.26    199504 354.11 (1 + sum(rate(199505) to rate(201707)))
    199505 4.25    199505 349.86 (1 + sum(rate(199506) to rate(201707)))
    ...    ...     ...    ...
    201704 0.79    201704   3.54 (1 + rate(201705) + rate(201706) + rate(201707))
    201705 0.93    201705   2.61 (1 + rate(201706) + rate(201707))
    201706 0.81    201706   1.80 (1 + rate(201707))
    201707 0.80    201707   1.00 (per definition)
    201708 0.14    201708   0.00 (per definition)
    

    现在我已经实现了一个VB.NET函数,它读取源表并生成计算表,但这是在运行时在每台客户机上完成的:

    Public Function AccumRates(targetDate As Date) As DataTable
        Dim dtTarget = Rates.Clone
        Dim targetId = targetDate.ToString("yyyyMM")
        Dim targetIdAnt = targetDate.AddMonths(-1).ToString("yyyyMM")
        For Each dr In Rates.Select("id<=" & targetId & " and id>199412")
            If dr("id") = targetId Then
                dtTarget.Rows.Add(dr("id"), 0)
            ElseIf dr("id") = targetIdAnt Then
                dtTarget.Rows.Add(dr("id"), 1)
            Else
                Dim intermediates =
                    Rates.Select("id>" & dr("id") & " and id<" & targetId).Select(
                        Function(ldr) New With {
                            .id = ldr.Field(Of Integer)("id"),
                            .rate = ldr.Field(Of Decimal)("rate")}
                        ).ToArray
                dtTarget.Rows.Add(
                    dr("id"),
                    1 + intermediates.Sum(
                        Function(i) i.rate))
            End If
        Next
        Return dtTarget
    End Function
    

    我的问题是如何将此作为查询放在我的数据库中,以便其他查询可以动态使用它,这些查询将使用这些累计费率将债务更新到任何给定日期。

    非常感谢!

    修改

    我设法创建了一个返回我想要的数据的查询,现在我只是不知道如何封装它,以便可以从另一个查询中调用它来传递任何id作为参数(这里我是用SET ...语句做的:

    SET @targetId=201708;
    SELECT 
        id AS id_acum,
        COALESCE(1 + (SELECT 
                        SUM(taxa)
                    FROM
                        tableSelic AS ts
                    WHERE
                        id > id_acum AND id < @targetId
                    LIMIT 1),
                IF(id >= @targetId, 0, 1)) AS acum
    FROM
        tableSelic
        WHERE id>199412;
    

    那是因为我对MySQL很陌生,我已经习惯了MS-Access,其中参数化查询非常容易创建。

2 个答案:

答案 0 :(得分:1)

例如:

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table
(id INT NOT NULL PRIMARY KEY
,rate DECIMAL(5,2) NOT NULL
);

INSERT INTO my_table VALUES
(201704,0.79),
(201705,0.93),
(201706,0.81),
(201707,0.80),
(201708,0.14);

SELECT *
     , CASE WHEN @flag IS NULL THEN @i:=1 ELSE @i:=@i+rate END i
     , @flag:=1 flag  
  FROM my_table
     , (SELECT @flag:=null,@i:=0) vars 
 ORDER 
    BY id DESC;
+--------+------+-------------+-------+------+------+
| id     | rate | @flag:=null | @i:=0 | i    | flag |
+--------+------+-------------+-------+------+------+
| 201708 | 0.14 | NULL        |     0 |    1 |    1 |
| 201707 | 0.80 | NULL        |     0 | 1.80 |    1 |
| 201706 | 0.81 | NULL        |     0 | 2.61 |    1 |
| 201705 | 0.93 | NULL        |     0 | 3.54 |    1 |
| 201704 | 0.79 | NULL        |     0 | 4.33 |    1 |
+--------+------+-------------+-------+------+------+
5 rows in set (0.00 sec)

答案 1 :(得分:0)

好的,我使用了一个函数:

CREATE FUNCTION `AccumulatedRates`(start_id integer, target_id integer) RETURNS decimal(6,2)
BEGIN
    DECLARE select_var decimal(6,2);
    SET select_var = (
        SELECT COALESCE(1 + (
            SELECT SUM(rate) 
            FROM tableRates 
            WHERE id > start_id AND id < target_id LIMIT 1
            ), IF(id >= unto, 0, 1)) AS acum 
        FROM tableRates 
        WHERE id=start_id);
    RETURN select_var;
END

他们是一个简单的查询:

SELECT *, AccumulatedRates(id,@present_id) as acum FROM tableRates;

其中@present_id作为参数传递。

感谢所有人,无论如何!