【问题标题】:GROUP BY with CASE WHEN?GROUP BY with CASE WHEN?
【发布时间】:2021-03-15 15:15:24
【问题描述】:

我的表 k 有:

num2 | count
aa1  | 10
aa2  | 5
bb   | 2
bb   | 4
cc   | 80

表 t 与:

num1 | num2
a    | aa1
a    | aa2
" "  | bb
" "  | bb
" "  | cc

现在我想获取每个 num1 的 MIN 和 MAX 计数,同时将 num1 中的 " " 替换为 num2(Fill rows in column A with value of column B if condition in column A is met):

用 num2 替换 num1 中的“”(有效):

SELECT (CASE
WHEN t.num1 = ' ' THEN TO_CHAR(k.num2)
ELSE t.num1
END) AS 'num1',
k.num2 AS 'num2',
k.count AS 'count'
--
FROM table1 AS k
--
LEFT JOIN table2 AS t
ON k.num2 = t.num2
--
WHERE k.count > 1
--
;

导致:

num1 | num2 | count
a    | aa1  | 10
a    | aa2  | 5
bb   | bb   | 2
bb   | bb   | 4
cc   | cc   | 80

但是使用 GROUP BY 获得每个 num1 的 MIN + MAX 不会:

SELECT (CASE
WHEN t.num1 = ' ' THEN TO_CHAR(k.num2)
ELSE t.num1
END) AS 'num1',
MIN(k.count) AS 'count_MIN',
MAX(k.count) AS 'count_MAX'
--
FROM table1 AS k
--
LEFT JOIN table2 AS t
ON k.num2 = t.num2
--
WHERE k.count > 1
--
GROUP BY (CASE
WHEN t.num1 = ' ' THEN TO_CHAR(k.num2
ELSE t.num1
END)
--
;

这应该导致:

num1 | count_MIN | count_MAX
a    | 5         | 10
bb   | 2         | 4
cc   | 80        | 80

但是当我运行上面的代码时,我在 DBeaver 中得到了错误:

SQL 错误 [4200]:不是有效的 GROUP BY 表达式

?

【问题讨论】:

  • 您的数据有一个表,但您的查询有两个,这使您的问题很不清楚。
  • @GMB 抱歉,添加了更多信息。现在好点了吗?
  • 您在 TO_CHAR(k.num2 中缺少右括号 )
  • 打错字了,原代码有括号。
  • 嗨@Vegam 在两个地方你缺少右括号(CASE WHEN 和 GROUP BY)。另外,您还没有看到我的答案,因为您在给表别名时还没有删除 AS 关键字?检查下面的答案...

标签: sql group-by case exasolution


【解决方案1】:

您的第二个查询不会引发错误:“SQL 错误 [4200]:不是有效的 GROUP BY 表达式”。结果是:“ORA-00907:缺少右括号”。

SELECT CASE WHEN t.num1 = ' ' THEN 
                 TO_CHAR(k.num2)
       ELSE 
                 t.num1
       END num1
       , MIN(k.count)  count_MIN
       , MAX(k.count)  count_MAX
FROM table1 k
LEFT JOIN table2 t ON k.num2 = t.num2
WHERE k.count > 1
GROUP BY CASE WHEN t.num1 = ' ' THEN 
                   TO_CHAR(k.num2)
         ELSE 
                   t.num1
         END;

这是一个演示:

DEMO

还有几件事:

  1. TO_CHAR 函数 - 需要在值后关闭括号
  2. 如果 else 结尾在括号内,您需要将大小写放入
  3. 您不需要将列别名放在单引号内
  4. COUNT - 不要将其用作列的名称
  5. 命名表别名时不要使用 AS 关键字

【讨论】:

  • 感谢您的回答。 To 3:不带引号 Oracle 以大写形式返回所有内容,我想要“num1”而不是“NUM1”。 To 4:列的名称与“count”不同,但请记住。至 5:为什么不呢?
  • 嗨@Vega 对于数字 3。好的,那么您需要使用双引号而不是单引号。所以“num1”而不是“num1”。对于 4 号。好的。因为 Oracle 不支持在 FROM 部分使用 AS 关键字。在为 SELECT MIN(k.count) AS count_MIN 之类的列命名别名时可以使用 AS 关键字,但在为 FROM table1 AS k 之类的表命名别名时不能使用它,您需要在没有 AS 关键字的情况下使用它。我找到了一个链接:techonthenet.com/oracle/alias.php
  • 3:“num1”有效,“num1”也有效。 4:FROM xxx AS 'yyy' 也可以,然后我可以在 SELECT 中使用 yyy.columnname。检查了我的数据库,它是 Exasol,而不是 Oracle。我的错。
  • 哦,那我明白了,我在评论 Oracle :)
【解决方案2】:

您可以使用coalesceTRIM函数如下:

SELECT COALESCE(TRIM(t.num1), t.num2) AS num1
       , MIN(k.count)  count_MIN
       , MAX(k.count)  count_MAX
FROM table1 k
LEFT JOIN table2 t ON k.num2 = t.num2
WHERE k.count > 1
GROUP BY COALESCE(TRIM(t.num1), t.num2) ;

【讨论】:

  • OP 大概区分了 T.NUM1 列中的单个空格和多个空格的字符串。只有一个空格应替换为 NUM2。此外,可能字符串 'cc' 和字符串 'cc ' 在 OP 的问题中是不同的;您的 TRIM 应用程序会将它们折叠成一个值。
  • 我能理解@mathguy。但我考虑得很实际
  • 我假设你的意思是“OP 在他的数据中不会有多个空格的字符串,或者像 'cc' 这样的字符串,所以我们可以忽略这种可能性”。如果这就是你的意思,那是非常危险的。这是我们最终遇到几乎无法诊断的大型、意外错误的主要方式之一。
  • 是的。你是对的@mathguy。我刚刚看到了示例数据和预期输出。
【解决方案3】:

我使用简化的表达式来获取修改后的 NUM1(用 NUM2 替换单个空格)。您必须在 SELECT 和 GROUP BY 中使用完全相同的表达式。

select nvl(nullif(t.num1, ' '), t.num2) as num1
     , min(count_)                      as min_count
     , max(count_)                      as max_count
from   t left outer join k on t.num2 = k.num2
group  by nvl(nullif(t.num1, ' '), t.num2)
order  by num1
;

NUM1  MIN_COUNT  MAX_COUNT
---- ---------- ----------
a             5         10
bb            2          4
cc           80         80

请注意,我在测试中使用了列名 COUNT_(带有尾随下划线); COUNT 是保留关键字,不能是列名。

【讨论】:

  • 您必须在 SELECT 和 GROUP BY 中使用完全相同的表达式 - 这不是 OP 的问题。
  • @VBoka - 我知道;我只是在提醒他们这个重要的事实。我没有说或暗示这是他的代码中的问题。我从头开始编写查询,我没有尝试修复他的代码(您可以通过比较它们来判断)。
  • 好的,我只是理解它就像你告诉 OP 他没有在 SELECT 和 GROUP BY 中使用相同的表达式。从我的角度来看,它的目标是这样的......
  • @VBoka - 我的意思是,如果我对修改后的 NUM1 使用不同的表达式,我必须记住在两个地方都更改它 - 而不仅仅是在 SELECT 中。提醒 OP、我自己以及任何查看他的代码然后查看我的代码的人。
猜你喜欢
  • 2014-05-15
  • 1970-01-01
  • 2015-07-21
  • 2019-03-27
  • 2017-03-22
  • 1970-01-01
  • 1970-01-01
  • 2020-10-26
  • 2021-12-22
相关资源
最近更新 更多