【问题标题】:Group By syntax while using Cross Join使用交叉连接时的 Group By 语法
【发布时间】:2016-02-21 08:34:54
【问题描述】:

我希望在下面的 SQL 中应用 Group By 条件,以便 O/P 显示带有 GP 的 POL#。

select t.POl#, (DEB.CUSTD - CRED.CUSTC) AS GP 
from (
        (
            select POL.SP_NUM POL#
            ,      sum(D.AMT) AS CUSTD 
            from   S_INVOICE D
            ,      S_ASSET POL 
            where  POL.ROW_ID           =   D.FN_ACCNT_ID 
            and    POL.SP_NUM           in  ('000','111','222') 
            and    D.DEBIT_TYPE         =   'Customer' 
            group by POL.SP_NUM
        ) DEB
        CROSS JOIN
        (
            select pol.SP_NUM POL#
            ,      sum(C.AMT) AS CUSTC 
            from   S_SRC_PAYMENT C
            ,      S_ASSET POL
            where  POL.ROW_ID           =   C.ASSET_ID 
            and    POL.SP_NUM           in  ('000','111','222') 
            and    C.CG_DEDN_TYPE_CD    =   'Customer' 
            group by POL.SP_NUM
        ) CRED
    ) t
    group by t.POL#

当我执行相同的操作时,我收到“ORA-00933:SQL 命令未正确结束”错误,其中光标指向“t”

请提供帮助。

Expected O/P:
POL#    GP
000     800
111     120
222     50

附加示例数据和解释以便更好地理解需求:

表 1:

S_ASSET
ROW_ID    POL#
1         000
2         111
3         222
4         333
5         444

表 2:

S_INVOICE (Debit Table)
FN_ACCNT_ID    POL#    DEBIT_TYPE          AMT
1              000     Customer            10
1              000     Customer            10
1              000     Insurer             5
2              111     Customer            10
3              222     Customer            10
3              222     Insurer             5
5              444     Insurer             10

表 3:

S_SRC_PAYMENT (Credit Table)
ASSET_ID    POL#    CG_DEDN_TYPE_CD     AMT
1           000     Insurer             10
1           000     Insurer             10
1           000     Customer            5
2           111     Insurer             10
3           222     Insurer             5
3           222     Insurer             5
3           222     Customer            5
5           444     Customer            10

根据此查询,我将考虑每个 POL# 的“客户”记录和对 AMT 求和。 (客户的每笔借记都将根据 POL# 向保险公司提供信用,反之亦然)

每个 POL# 客户的预期 O/P(借方总和 - 贷方总和)

POL #       AMT (GP)
000         15
111         10
222         5
333         0
444        -10

【问题讨论】:

  • 什么是 S_ASSET 中的唯一键?您正在使用列 SP_NUM 和 ROW_ID。其中一个是否唯一标识表中的记录?也许两者兼而有之?或者也许只是两者的结合?
  • S_ASSET 的唯一键将为 ROW_ID,但对于 GROUPING SAKE SP_NUM 将被视为重复键。

标签: sql group-by cross-join


【解决方案1】:

您显然只想获取每个 s_asset 的 deb 和 cred,然后聚合以获得总和。您可以在没有连接的情况下执行此操作,而是直接对总和进行子查询:

select 
  sp_num as pol#,
  sum(<get deb sum for the pol.row_id here>) - sum(<get cred sum for the pol.row_id here>)
from s_asset pol 
where sp_num in ('000','111','222')
group by sp_num;

完整的查询:

select 
  sp_num as pol#,
  coalesce(sum(
    (
      select sum(deb.amt)
      from s_invoice deb
      where deb.fn_accnt_id = pol.row_id
      and deb.debit_type = 'Customer' 
    )
  ), 0) -
  coalesce(sum(
    (
      select sum(cred.amt) 
      from s_src_payment cred
      where cred.asset_id = pol.row_id
      and cred.cg_dedn_type_cd = 'Customer' 
    ), 0)
  ) as gp
from s_asset pol 
where sp_num in ('000','111','222')
group by sp_num;

与连接相同:

select 
  pol.sp_num as pol#,
  coalesce(sum(deb.total), 0) - coalesce(sum(cred.total), 0) as gp
from s_asset pol
left join
(
  select fn_accnt_id as pol_row_id, sum(deb.amt) as total
  from s_invoice
  where  debit_type = 'Customer' 
  group by fn_accnt_id 
) deb on deb.pol_row_id = pol.row_id
left join
(
  select asset_id as pol_row_id, sum(amt) as total
  from s_src_payment
  where  cg_dedn_type_cd = 'Customer' 
  group by asset_id
) cred on cred.pol_row_id = pol.row_id
group by pol.sp_num;

【讨论】:

  • 哇!!...接下来的几个小时我将完全研究和理解你写的查询。太感谢了。我将对完整的列执行相同的操作,然后将您的答案标记为正确/接受。
  • umm...当每个 POL 的贷方和/或借方表中没有记录时,结果不正确。记录数是正确的,但 GP 正在重复上一个值,其中应该是 null/0...
  • 这很奇怪。当没有贷记和/或借记记录时,总和为空。 COALESCE 将 null 更改为零。我看不出一个值会被重复。你知道 sqlfiddle.com 吗?在那里,您可以使用示例数据设置表格。尝试找到产生不想要的结果的样本数据,并给我们 sqlfiddle 链接进行检查和验证。
  • 您的语法完全正确。我的测试区有一些垃圾数据,我将创建新的有意义的记录并进行验证。至于我分享的示例数据,效果很好。
【解决方案2】:

这个语法

from ( (select ...) CROSS JOIN (select ...) )

无效。一个 JOIN 属于一个 FROM。因此,其中任何一个都是正确的:

from ( SELECT * FROM (select ...) CROSS JOIN (select ...) )

from (select ...) CROSS JOIN (select ...)

但是,您确定要 CROSS JOIN 吗?两个子查询都为您提供 POL 编号和数据,而不是在 POL# 上加入它们,而是交叉加入结果,因此您将获得所有 POL# 组合。

【讨论】:

  • 是的,Thorsten,你是对的。当我测试多条记录的查询时,它失败了。我将使用示例数据更新线程,以便您了解我的要求。也许根本不需要交叉连接。
猜你喜欢
  • 2019-09-01
  • 1970-01-01
  • 2021-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-07
  • 2019-01-15
  • 1970-01-01
相关资源
最近更新 更多