【问题标题】:SQL, invoice statements, current and past duesSQL、发票报表、当前和过去的会费
【发布时间】:2016-08-16 17:57:24
【问题描述】:

SQL 新手,了解基本查询,尝试编写比我的知识更高级的东西,如果有人可以提供,需要一些帮助。我已经尝试过模板代码并根据我的需要进行定制,但没有成功。

我正在使用 1 个表,并尝试让查询显示客户当前余额 0-30 天,以及 30-60 、 60-90 、 90-120 、 120+ 天之间的任何过期日期。

table: c_inv_h
columns: comp_code, cust_code, inv_num, inv_date, inv_tp, inv_amt, inv_tax1, inv_tax2

示例数据

comp_code, cust_code, inv_num, inv_date, inv_tp, inv_amt, inv_tax1, inv_tax2
M1, 100068, 1, 2016-08-11, RCPT, 103.48, 4.5, 8.98
M1, 100068, 2, 2016-07-11, RCPT, 103.48, 4.5, 8.98
M1, 100068, 3, 2016-06-11, RCPT, 103.48, 4.5, 8.98
M1, 200027, 4, 2016-05-11, RCPT, 103.48, 4.5, 8.98
M1, 200027, 5, 2016-04-11, RCPT, 103.48, 4.5, 8.98

我希望查询显示的内容:

comp_code, cust_code, CurrentBalance, 30-60, 60-90, 90-120, 120+
M1, 100068, 116.96, 233.92, 0, 0, 0
M1, 200027, 0, 233.92, 0, 0, 0
M1, 200027, 0, 0, 0, 0, 233.92

到目前为止我已经尝试过什么

SELECT comp_code, cust_code, inv_num, inv_date, sum(inv_amt) + sum(inv_tax1)
+ sum(inv_tax2) as InvoiceTotal,
DATEDIFF(day, inv_date, sysdate as Numberofdays, 'CurrentBalance' = 
CASE WHEN DATEDIFF(day,inv_date, sysdate < 30 then InvoiceTotal END,
'30_days' = CASE WHEN DATEDIFF(day, inv_date, sysdate between 30 AND 60
Then InvoiceTotal WHEN DATEDIFF(day, inv_date, sysdate > 90 Then
InvoiceTotal END
FROM c_inv_h
WHERE comp_code='M1'
GROUP BY comp_code, cust_code

这可能与我想要实现的目标相去甚远,但我正在努力解决它。

提前非常感谢!!

【问题讨论】:

  • 艾伦欢迎来到stackoverflow!您的问题有一个良好的开端,但还应根据您的示例数据包括您想要的结果,并向我们展示您尝试过的东西。如果它偏离或不起作用,请不要担心它只是帮助我们知道我们正在帮助您而不是为您做这件事,并且可以对您所需的逻辑产生一些额外的见解。
  • 感谢马特。我编辑了我的帖子。
  • 您可以使用条件聚合来创建这样的数据透视表。但是根据哪个数据库/rdbms(sql-server、oracle、mysql),您使用的系统可能还有其他一些可用的选项?也可以在您希望查询显示的内容中放置一行 daa,以帮助人们更好地可视化
  • 我已按您的要求输入了示例行。使用 mysql。谢谢。

标签: sql


【解决方案1】:

您对条件聚合的思考是正确的。您只需删除未参与聚合的列并清理语法错误。

SELECT
    comp_code
    ,cust_code
    ,SUM(CASE
          WHEN DATEDIFF(CURDATE(),inv_date) < 30
          THEN COALESCE(inv_amt,0.00) + COALESCE(inv_tax1,0.00) + COALESCE(inv_tax2,0.00)
          ELSE 0
        END
    ) AS CurrentBalance
    ,SUM(CASE
          WHEN DATEDIFF(CURDATE(),inv_date) >= 30 AND DATEDIFF(CURDATE(),inv_date) < 60
          THEN COALESCE(inv_amt,0.00) + COALESCE(inv_tax1,0.00) + COALESCE(inv_tax2,0.00)
          ELSE 0
        END
    ) AS "30-60"
    ,SUM(CASE
          WHEN DATEDIFF(CURDATE(),inv_date) >= 60 AND DATEDIFF(CURDATE(),inv_date) < 90
          THEN COALESCE(inv_amt,0.00) + COALESCE(inv_tax1,0.00) + COALESCE(inv_tax2,0.00)
          ELSE 0
        END
    ) AS "60-90"
    ,SUM(CASE
          WHEN DATEDIFF(CURDATE(),inv_date) >= 90 AND DATEDIFF(CURDATE(),inv_date) < 120
          THEN COALESCE(inv_amt,0.00) + COALESCE(inv_tax1,0.00) + COALESCE(inv_tax2,0.00)
          ELSE 0
        END
    ) AS "90-120"
    ,SUM(CASE
          WHEN DATEDIFF(CURDATE(),inv_date) >= 120
          THEN COALESCE(inv_amt,0.00) + COALESCE(inv_tax1,0.00) + COALESCE(inv_tax2,0.00)
          ELSE 0
        END
    ) AS "120+"
FROM
    c_inv_h
WHERE
    comp_code='M1'
GROUP BY
    comp_code, cust_code
;

我正在使用 COALESCE 来确保存在一个值,因为在添加列时,如果添加 1 + NULL + 1,结果将为 NULL。当使用聚合函数时,例如SUM() 它将忽略 NULL 值。因为您根据您的数据集同时使用这两种方法,所以您可能需要将 0 分配给 COALESCE 提供帮助的 NULL。

接下来我不使用 BETWEEN,因为 BETWEEN 包含比较的双方,所以如果您说一列介于 30 和 60 之间,另一列介于 60 和 90 之间,并且金额是逾期 60 天,它将在两列。

最后一个示例输出与您提供的示例数据不正确,因为日期分别为 5、36、66、97 和 127 天,但我很确定我明白您想要什么。

希望对您有所帮助。

【讨论】:

  • 谢谢马特。请与我裸露,慢慢学习和理解您所写的内容。我已经尝试测试该脚本,但我收到了错误,例如无效的表名,所以我从@c_inv_h 中取出@,然后我收到错误,因为 DATEDIFF 是无效标识符。然后我尝试用 STARTDATE 替换 DATEDIFF,这也是一个无效的标识符。 'java.sql.SQLException: ORA-00903: 无效表名', 'java.sql.SQLException: ORA-00904: "DATEDIFF": 无效标识符'
  • 对不起,我把 @ 符号留在了那里,我使用 sql-server 表变量来测试和构建查询。我也没有将一些语法更改为 mysql 版本。我根据查看您的查询快速构建了查询,我想我应该在一开始就在 mysql 中完成它。 SQLFiddle 是一个网站,可让您在不同的数据库中测试一些代码,这里是一个测试链接,显示更新的答案现在正在运行。 sqlfiddle.com/#!9/40271/4
  • 谢谢马特,我能够让你的脚本在 MySQL 中运行,然后我在我的公司服务器数据库上尝试了它,但没有用。我是个白痴,数据库在 Oracle 而不是 mysql 上运行,所以我试图将其调整为 Oracle 函数名称。 ' SELECT comp_code, cust_code, CASE WHEN TO_DATE(sysdate) - TO_DATE(inv_date)
  • 老实说,很难在评论中遵循代码,您可以在此处更新您的问题并对其进行格式化。但是 TO_DATE 是一个问题,尽管我怀疑您是否需要转换这些值,因为它们已经是日期,因此语法可能只是 (sysdate - inv_date)
  • 嗨,马特,谢谢。您删除 TO_DATE 是绝对正确的。一旦删除并遵循您的语法,我就能够让查询在 Oracle 中工作。
猜你喜欢
  • 2017-05-01
  • 1970-01-01
  • 2016-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-17
  • 1970-01-01
相关资源
最近更新 更多