尽管对所有关键变量进行了分组,SQL 还是重复?

Posted

技术标签:

【中文标题】尽管对所有关键变量进行了分组,SQL 还是重复?【英文标题】:SQL duplicates despite grouping on all key variables? 【发布时间】:2021-12-04 19:09:31 【问题描述】:

我是 SQL 新手,并且将它用于工作,因此我将在下面的查询中审查列的真实名称。

我正在编写一个查询,其中必要的数据分布在 3 个表中。我有一个网络,用户从不同节点发送和接收包,我想查看每个用户在每个时期从网络内部的每个节点发送和接收多少包(这些不仅仅是分组变量,而是目标表我试图存储它的地方有这些列的组合,除了作为主键的包数)。正确的结果会给我一个表格,其中包含标识列、周期、节点以及接收和发送的包裹数量。

第一个表 scm.flow 包含有关用户的详细信息以及他们在每个时期发送和接收的包裹数量。我需要从这里分组的列是 3 列,用于标识唯一用户及其所属的单位,并且该表还包含一个列“number_packs”,其中包含接收的包数 (+xxxx) 和发送的包数 (-xxxx )。其中一些包是从网络内部和外部的源发送或接收的。那些在内部发送或接收的人会在 scm.internal 表中记录他们的简称,在第三个表 scm.node_names 中,他们可以与我想要的全名链接。

虽然我可以运行查询并获得乍一看似乎正确的结果,但我无法存储它,因为我收到错误 ORA-01452。我将代码作为视图运行,在该视图中,我使用 have 和 count(*) 检查分组变量中的重复值,尽管我对这些变量进行了分组,并对其余变量使用聚合函数,但这里仍然存在重复值。

我写的查询是这样的:

select id1, id2, id3, node, period, received, sent
from (
 select id1, id2, id3, 

 case when (node is not null) as node else 'Failed to record' end as node,
 period,
 sum(case when (trans_type = 'T1' and number_packs > 0) then number_packs else 0 end) as received,
 sum(case when (trans_type = 'T2' and number_packs < 0) then number_packs else 0 end) as sent

 from (
  tr.id1, tr.id2, tr.id3, tr.int_flag, tr.description, tr.period, tr.trans_t_no,
  it.trans_type,
  case when (it.trans_type = 'T1' and number_packs > 0) then kt.rec_from_node else tk.sent_from_node as node,
  number_packs,
  
  from scm.flow tr

  left join (
   select t.id1, t.trans_type, t.trans_t_no, t.rec_from_code, t.sent_from_code
   from (select id1, trans_type, trans_t_no, rec_from_code, sent_from_code
         from scm.internal) t) it
    on tr.id1 = it.id1 and tr.trans_t_no = it.trans_t_no and tr.int_flag = '1' and tr.description like 'GI%'
     
   left join (select code, node from scm.node_names) kt
      on kt.code = it.received_from_code
   left join (select code, node from scm.node_names) tk
      on tk.code = it.sent_from_code

 where tr.int_flag = '1')

group by id1, id2, id3, node, period) k

where received > 0 or sent < 0 ;

在此查询的视图上使用 have 和 count(*) 时,我注意到 2 件事:1. 仅当 node = '无法记录'时才会发生重复,2. 发送和接收都是 0,这不应该因为 number_packs 列总是有一个正数或负数,所以它永远不会为 null 或 0。

我仍然看不出我的代码如何导致这些结果。我想知道为什么会出现带零的重复项,以及如何修复我的查询以避免该问题?

(我知道添加一些示例数据是最佳做法,但我想避免它,因为即使更改了列名,它也是潜在的敏感数据。

【问题讨论】:

如果您需要避免敏感数据,请创建一些示例数据。无论如何,这就是你应该测试的方式。 您的问题是关于错误消息还是错误结果?他们应该是两个不同的问题。处理错误消息,然后用示例数据打开另一个问题,展示您正在努力处理的行为。您还应该隔离给您带来问题的问题的最小过去,并且只包含那部分代码。请阅读:***.com/help/minimal-reproducible-example 有时包括表的rowids可以告诉你哪些行被复制了。 请不要因更改(或在本例中完全删除)问题而使您获得的答案无效。如果您认为问题需要改进,请继续改进。 【参考方案1】:

您至少有一个语法错误...

case when (node is not null) as node else 'Failed to record' end as node,

CASE 表达式中间的as node 不应该存在...

(node is not null) as node

应该是THEN node

case when (node is not null) then node else 'Failed to record' end as node,

或者,只需使用COALESCE()...

COALESCE(node, 'Failed to record') AS node, 

【讨论】:

以上是关于尽管对所有关键变量进行了分组,SQL 还是重复?的主要内容,如果未能解决你的问题,请参考以下文章

当值在sql中重复时如何对列进行分组

数据库sql去重

sql语句去重

SQL语句中,如果有group by 和order by两个语句,是先分组还是先排序?

SQL语句中,如果有group by 和order by两个语句,是先分组还是先排序?

group by小结