【问题标题】:Calculate in join in sql在sql中加入计算
【发布时间】:2015-09-29 17:43:53
【问题描述】:

我正在尝试在 sql 2008 的连接中实现交错计算。我可以为 1 个作业 ID 设置 n 行。我在下面创建了一个示例

CREATE TABLE Job
(
  JobID INT NOT NULL,
  Amount INT NOT NULL
);

INSERT INTO Job (JobID, Amount)
    VALUES (1, 25),
        (1, 45),
        (1, 40),
        (2, 25),
        (3, 26),
        (3, 26);

现在JobID = 1 的折扣是 80 ,所以我期望的查询结果输出如下:

如果是 Amount > Discount ,那么显示 finalvalue = Amount - Discount 但如果 Amount < Discount ,则显示 Finalvalue = Amount - Amount , 如果 Discount 仍然存在,则从后续行中扣除相同的值。

Job ID  Amount  FinalValue
1        25       0
1        45       0
1        40      30

所有这些都可以在一个连接中完成吗?

【问题讨论】:

  • 请包括折扣表的结构,以便制定正确的答案。
  • 您是否有 ID 或创建日期字段可用于告知应应用折扣的顺序?例如,在您的示例中,在将折扣应用于 40 行之前,您是如何决定将折扣应用于 25 和 45 行的?

标签: sql sql-server sql-server-2008


【解决方案1】:

你在这里:

编辑:注意:您应该添加一列进行排序。我的方法是按 JobID 进行分区和排序,这使得输出随机......

编辑:抱歉,没有添加表格...

CREATE TABLE Job
(
    JobID INT NOT NULL,
    Amount INT NOT NULL
);

INSERT INTO Job (JobID, Amount)
    VALUES (1, 25), (1, 45), (1, 40), (2, 25), (3, 26), (3, 26);

CREATE TABLE Discount
(
    JobID INT NOT NULL,
    Discount INT NOT NULL
);
INSERT INTO Discount(JobID,Discount)VALUES(1,80),(2,0),(3,10);
    WITH myCTE AS
    (
        SELECT ROW_NUMBER() OVER(PARTITION BY Job.JobID ORDER BY Job.JobID) AS inx
              ,Job.JobID
              ,Job.Amount
              ,Discount.Discount     
        FROM Job
        INNER JOIN Discount ON Job.JobID=Discount.JobID
    )
    SELECT * FROM myCTE
    CROSS APPLY
    (
        SELECT SUM(x.Amount)
        FROM myCTE AS x
        WHERE x.JobID=myCTE.JobID
          AND x.inx<=myCTE.inx  
    ) AS AmountCummulativ(AmountCummulativ)
    CROSS APPLY(SELECT AmountCummulativ-myCTE.Discount) AS DiscountCalculated(DiscountCalculated)
    CROSS APPLY(SELECT CASE WHEN DiscountCalculated<0 THEN 0 ELSE DiscountCalculated END) AS DiscountResolved(DiscountResolved)

希望对你有帮助

【讨论】:

    【解决方案2】:

    我认为您要查找的内容可以使用 case 语句来完成

    select a.jobid,a.Amount,case when a.amount > b.discount then a.amount - b.discount else 0 end final_value
    

    从Job a 内加入Job_discount b on a.jobid = b.jobid

    你可以在这里查看结果http://sqlfiddle.com/#!3/f9a46/1

    我不得不假设折扣表结构

    【讨论】:

    • 你的 SQLFiddle 真的返回 OP 的数据吗?我对 OP 的理解是,要完成的金额是累积的,比“折扣”更好的词可能是“Acconto”......
    • Vanamali,感谢你的努力......但我认为你只是从金额中直接减去折扣......thts nt case..你必须照顾所有的订单项......
    【解决方案3】:

    我为 Job 表(称为 JobOrder)添加了一些序列(行号),以增加总和。您可以像现在一样更改 JobId、Amount 的顺序!

    With JobOrder as (
      -- Job order by id and amount
      select row_number() over (order by JobID, Amount asc) as rowno, JobId, Amount from Job
    ),
    JobSumIncr as (
      select 
      JobID, 
      Amount, 
      (select sum(Amount)
       from JobOrder j2
       where j2.JobID = j.JobID and j2.RowNo <= j.RowNo
      ) as AmountTotal
      from JobOrder j
    )
    select 
      j.JobID,
      j.Amount,
      j.AmountTotal,
      d.Discount,
      (case when d.Discount>=j.AmountTotal then 0 else j.AmountTotal-d.Discount end) as FinalValue
    from
      JobSumIncr j left join Discount d on j.JobID = d.JobID; 
    

    假设您的折扣表类似于:

    CREATE TABLE Discount (
        JobID INT,
        Discount INT 
    );
    

    SqlFiddle here! 要获得更安全的 Sql(检查 null 值并查看剩余折扣),请参阅此 SQLFiddle too

    跟踪剩余折扣的版本,参见上面的 sqlfiddle-2。

    【讨论】:

    • 嗨,简单,感谢您的努力..您的答案非常接近,但在少数情况下会中断...例如,如果我在 JOB 表中添加另一行,例如 (1,50)...将打破..直到折扣剩余 nt 变为 0 为止,您的查询就像一种享受...
    • 嗨@XanderKage 我不明白你的评论。向 jobid 1 添加另外的 50 将如何打破?我签入了 sqlfiddle sqlfiddle.com/#!6/58efd7/1,它的作用就像魅力一样,discountleft 匹配并且最终值是正确的;)或者您是否也期望最终值增加?就像 jobid 1 一样,它会变成 0、0、30,然后是 50?
    • 嗨,很简单,我的错..它工作正常,但我发现 1 种情况它中断了 :( 让我们假设折扣低于最低金额......在它中断的情况下......我更新了JOB ID = 4 的折扣为 5 以进行测试...感谢您的努力...
    • 你能解释一下吗。 Jobid 4 的 Job 表中有多少? jobid 4有折扣吗?您写的折扣 5 是针对 jobid4,但工作表中的金额是多少?
    猜你喜欢
    • 2013-09-21
    • 1970-01-01
    • 2014-04-15
    • 2017-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-01
    • 1970-01-01
    相关资源
    最近更新 更多