SQL查询,外连接,cte?需要使用“左”值修复运行总计

Posted

技术标签:

【中文标题】SQL查询,外连接,cte?需要使用“左”值修复运行总计【英文标题】:SQL query, outer join, cte? Need to fix running total with "left" value 【发布时间】:2019-03-13 14:55:47 【问题描述】:

我几天来一直在尝试纠正这个查询。基本上在每个acount_nogroup 的一组中,只需要扣除小于最大组的金额

基本上,账户 104 的 maxgroup 为 99,第一个金额是 75,因为 take 将是 75,left 将是 24,那么对于下一个 B 组,即使需要的数量是 64,因为只剩下 24,所以 B 组将只得到 24,之后什么都没有,所以 D 组将剩下 0。

基本上我的表可以有这样的值

DECLARE @table AS TABLE(acc_no INT, [group] CHAR(1), [maxgroup] INT, amount INT)

INSERT INTO @table VALUES
(101, 'A', 70, 0),
(101, 'B', 70, 50),
(101, 'C', 70, 0),
(101, 'D', 70, 20),
(102, 'A', 95, 30),
(102, 'B', 95, 0),
(102, 'C', 95, 5),
(102, 'D', 95, 10),
(103, 'A', 80, 40),
(103, 'B', 80,15),
(103, 'C', 80, 10),
(103, 'D', 80, 5),
(104, 'A', 99.53, 75),
(104, 'B', 99.53,64),
(104, 'D', 99.53, 0.53),

(105, 'A', 21.5, 75),
(105, 'D', 21.5,6)



SELECT t.acc_no, 
    t.[group],
    t.maxgroup,t.amount,
    CASE WHEN t1.assigned = 0 THEN NULL ELSE t.amount END AS taken, 
    CASE WHEN t1.assigned = 0 THEN NULL ELSE (t.maxgroup - t1.assigned) END [left]
FROM @table t
OUTER APPLY(SELECT SUM([amount]) AS assigned 
            FROM @table t1 WHERE t1.acc_no = t.acc_no AND t1.[group] <= t.[group]) t1

这是我期望的结果:

 acc_no group   maxgroup    amount  taken   left
101 A   70      0   NULL    NULL
101 B   70      50  50  20
101 C   70      0   0   20
101 D   70      20  20  0
102 A   95      30  30  65
102 B   95      0   0   65
102 C   95      5   5   60
102 D   95      10  10  50
103 A   80      40  40  40
103 B   80      15  15  25
103 C   80      10  10  15
103 D   80      5   5   10
104 A   99      75  75  24
104 B   99      64  24  0    --<<
104 D   99      0   0   0
105 A   21      75  21  0
105 D   21      6   0   0

不幸的是,我的查询为acc_no=104left 列提供了负值。

【问题讨论】:

嗨。很高兴看到minimal reproducible example 的代码部分。但它需要一个明确的规范。 “基本上”并没有使模糊性变得清晰。 (当它没有介绍或总结清楚的完整细节时,它的存在表明作者知道他们不清楚但无论如何都写得不清楚。他们为什么要这样做?)您对输出如何作为输入函数的描述是难以理解的。请使用足够的单词、短语和句子来清楚。不要试图将所有内容都塞进一个句子或段落中。请参阅它们的中间表达式和示例值。 非常感谢 Philipxy,我会记住这一点。还在学习stackover flow的标准。它对我很有帮助,非常感谢您在这方面对我的耐心。 【参考方案1】:

你们很亲密:

CASE 
  WHEN t1.assigned = 0 THEN NULL 
  WHEN t.maxgroup < t1.assigned THEN 0 --<< that's it
  ELSE (t.maxgroup - t1.assigned) 
END [left]

但我的建议是:

SELECT t.acc_no, 
    t.[group],
    t.maxgroup,
    t.amount,
    CASE 
      WHEN t.amount = 0 THEN 0
      WHEN t.maxgroup < (t.running_total-t.amount) THEN 0
      WHEN t.maxgroup < t.running_total THEN t.amount - (t.running_total - t.maxgroup)
      ELSE t.amount
    END taken,
    CASE 
      WHEN t.maxgroup < t.running_total THEN 0
      ELSE t.maxgroup - t.running_total
    END [left]
FROM (
  SELECT t.acc_no, 
      t.[group],
      t.maxgroup,
      t.amount,
      SUM(t.amount) OVER(PARTITION BY t.[acc_no] ORDER BY t.[group] ROWS UNBOUNDED PRECEDING) running_total
  FROM stock t
) t
order by 1, 2

这一项只会对源表进行一次扫描。而不是使用子查询方法的许多循环。

http://sqlfiddle.com/#!18/ce2f5/12

【讨论】:

谢谢,谢谢,非常感谢,效果很好。有一个问题,为什么我们需要订购,1,2 在做什么?我确实希望根据组的顺序计算运行总数,但按 1,2 排序看起来不像这样做。请提出建议。 order by 正在对最终输出进行排序,不影响运行总计。 1, 2 - 允许但不欢迎按数字引用输出列的方法,仅适用于 order by。测试查询很好,而不是 prod(坏风格)。 非常感谢.. 所以在这种情况下 1,2 将是 t.acc_no 和 t.group 列?【参考方案2】:

为了保持查询逻辑,您可以跟踪每个组的前一行总数,如下所示:

SELECT t.acc_no, 
    t.[group],
    t.maxgroup, t.amount, 
    CASE WHEN A.previous_assigned + t.amount <= t.maxgroup THEN t.amount
    ELSE CASE When (t.maxgroup - A.previous_assigned) > 0 Then (t.maxgroup - A.previous_assigned)
        ELSE 0
        END 
    END AS taken, 
    CASE WHEN  (t.maxgroup - A.previous_assigned - t.amount) <= 0 THEN 0 
    ELSE (t.maxgroup - A.previous_assigned - t.amount) 
    END AS [left]
FROM @table t
OUTER APPLY(SELECT SUM([amount]) AS assigned, (SUM([amount]) - t.amount) AS previous_assigned
            FROM @table t1 WHERE t1.acc_no = t.acc_no AND t1.[group] <= t.[group]) As A;

【讨论】:

非常感谢,如果我要添加以下行 (107, 'A', 100,20), (107, 'B', 100, 35), (107, 'D', 100 , 65), (107, 'C', 100, 50) 在表中,这不会给出正确的结果。我想我现在已经找到了解决方案,非常感谢您在这里提供的帮助。

以上是关于SQL查询,外连接,cte?需要使用“左”值修复运行总计的主要内容,如果未能解决你的问题,请参考以下文章

如何在 LINQ 中使用左外连接进行 SQL 查询?

对两个 MySQL 查询执行左外连接?

Hive SQL 多个左外连接查询在其结果中缺少记录

内连接,左连接,右连接,全外链接

转载-- SQL连接查询2 外连接(左右联接查询)

SQL 优化左外连接查询