0

我正在做一些关于财务账户的报告,我需要根据初始数字对各个级别的值求和...例如,对以 0(01、011、012 ..)或从 1( 1, 10, 111...),或以 111 (111,1112,1113...) 等开头

这是简化的示例表:

CREATE TABLE account(id, acctNo, credit) AS (
    VALUES
       (1, '01', 100)
      ,(2, '011', 200)
      ,(3, '0112', 300)
      ,(4, '014', 400)
      ,(5, '0144', 500)
      ,(6, '0148', 600)
      ,(7, '01120', 100)
      ,(8, '01121', 100)
      ,(9, '0140', 50)
      ,(10,'02', 50)
      ,(11,'021', 50)
      ,(12,'1', 50)
      ,(13,'10', 100)
      ,(15,'100', 50)    
      ,(14,'1021', 50)
      ,(16,'202', 50)
      ,(17,'221', 50)
      ,(18,'4480', 50)
      ,(19,'447', 50)
      ,(20,'5880', 50)
    )

我设法做到了,但它有点健壮的 SQL,有没有更好的解决方案? 这是代码:

WITH
    a AS (SELECT SUBSTRING(acctNo,1,1) AS LEVEL,
    SUM(credit)  AS sum1 FROM account GROUP BY LEVEL
    ORDER BY LEVEL),
    b AS
   (SELECT SUBSTRING(acctNo,1,2) AS level2,
    SUM(credit) FROM account GROUP BY level2
    ORDER BY level2),
        c AS
   (SELECT SUBSTRING(acctNo,1,3) AS level3,
    SUM(credit) FROM account GROUP BY level3
    ORDER BY level3),
    d AS (SELECT SUBSTRING(acctNo,1,4) AS level4,
    SUM(credit) FROM account GROUP BY level4
    ORDER BY level4),
     e AS (SELECT SUBSTRING(acctNo,1,5) AS level5,
    SUM(credit) FROM account GROUP BY level5
    ORDER BY level5)

 SELECT * FROM
 (SELECT a.* FROM a
 UNION (SELECT b.* FROM b WHERE char_length(level2)>=2)
 UNION (SELECT c.* FROM c WHERE char_length(level3)>=3)
 UNION (SELECT d.* FROM d WHERE char_length(level4)>=4)
 UNION (SELECT e.* FROM e WHERE char_length(level5)>=5)) a
 ORDER BY LEVEL

这仅适用于 5 个级别(五位数字)...有一些通用的解决方案吗?如果明天我需要 6 个级别,等等...

这是SQL 小提琴

谢谢。

4

2 回答 2

3

耶 generate_series!

SELECT substring(a.acctNo from 1 for g.g) as level, sum(a.credit)    
FROM account a, generate_series(1,5) g
where length(a.acctNo) >= g.g
group by 1
order by 1
于 2013-06-05T15:08:22.263 回答
1

为了使 maniek 的答案通用:

with levels as (
    select g
    from generate_series(
        1,
        (select max(length(acctNo)) from account)
    ) g
)
select substring(acctNo from 1 for l.g) as level, sum(a.credit)    
from account a, levels l
where length(acctNo) >= l.g
group by 1
order by 1
于 2013-06-05T16:15:19.823 回答