【问题标题】:Oracle group by only ONE columnOracle 仅按一列分组
【发布时间】:2017-10-10 17:23:09
【问题描述】:

我在 Oracle 数据库中有一个表,它有 40 列。 我知道如果我想进行 group by 查询,select 中的所有列都必须在 group by 中。

我只是想做:

select col1, col2, col3, col4, col5 from table group by col3

如果我尝试:

select col1, col2, col3, col4, col5 from table group by col1, col2, col3, col4, col5

它没有给出所需的输出。

我已经搜索过这个,但没有找到任何解决方案。我使用某种 Add() 或 count(*) 函数找到的所有查询。

在 Oracle 中不能简单地按一列分组吗?

更新:

抱歉,不够清楚。

我的桌子:

+--------+----------+-------------+-------+
| id     | col1     | col2        | col3  |
+--------+----------+-------------+-------+
| 1      | 1        | some text 1 | 100   |
| 2      | 1        | some text 1 | 200   |
| 3      | 2        | some text 1 | 200   |
| 4      | 3        | some text 1 | 78    |
| 5      | 4        | some text 1 | 65    |
| 6      | 5        | some text 1 | 101   |
| 7      | 5        | some text 1 | 200   |
| 8      | 1        | some text 1 | 200   |
| 9      | 6        | some text 1 | 202   |
+--------+----------+-------------+-------+

并通过运行以下查询:

select col1, col2, col3 from table where col3='200' group by col1;

我将得到以下所需的输出:

+--------+----------+-------------+-------+
| id     | col1     | col2        | col3  |
+--------+----------+-------------+-------+
| 2      | 1        | some text 1 | 200   |
| 3      | 2        | some text 1 | 200   |
| 7      | 5        | some text 1 | 200   |
+--------+----------+-------------+-------+

【问题讨论】:

  • 你不能这样分组。你需要什么?也许如果您分享一些示例数据/输出,我们可以提供帮助
  • order by 而不是group by? select col1, col2, col3, col4, col5 from table order by col3 不,当您有多个列时,您不能按单个列分组。想想看。如果我们在第一行有 a,b,c,在第 2 行有 x,y,c。并且我们只按第 3 列分组......系统应该为第 1 列和第 2 列选择什么? a 还是 x? b 还是 y?系统无法为您决定这就是它无效的原因。 (但如果您更改设置,则在 mySQL 的顺序版本和当前版本中有效)
  • 简单地说,在大多数 RDBMS 引擎中,没有聚合的 group by 是没有意义的,因为聚合的行数必须从原始集合中减少,并且 group by 解释了聚合的级别应该发生。当您有重复的记录并且您需要删除重复的记录时,DISTINCT 是有意义的。它可以选择 a 或者它可以选择 x,并且它可以根据一次执行到下一次执行而有所不同。这就是为什么大多数引擎不扩展组的原因

标签: sql oracle group-by


【解决方案1】:

这里长评;

是的,你不能那样做。想想看……如果你有这样的桌子:

Col1 Col2 Col3
A    A    1
B    A    2
C    A    3

而您仅按Col2 分组,这将分组为一行...Col1 和Col3 会发生什么?两者都有 3 个不同的行值。 您的 DBMS 应该如何显示这些?

Col1 Col2 Col3
A?   A    1?
B?        2?
C?        3?

这就是为什么您必须按所有列分组,或者以其他方式聚合或连接它们。 (SUM()、MAX()、MIN()等)

向我们展示您希望结果的外观,我相信我们可以为您提供帮助。

编辑 - 答案:

首先,感谢您更新您的问题。您的查询没有id,但您的预期结果有,所以我将分别回答每个问题。

没有id

您仍然需要按所有列分组以实现您的目标。让我们来看看吧。

如果您在没有任何分组的情况下运行查询:

select col1, col2, col3 from table where col3='200'

你会得到这个:

+----------+-------------+-------+
| col1     | col2        | col3  |
+----------+-------------+-------+
| 1        | some text 1 | 200   |
| 2        | some text 1 | 200   |
| 5        | some text 1 | 200   |
| 1        | some text 1 | 200   |
+----------+-------------+-------+

所以现在您只想看到col1 = 1 行一次。但要这样做,您需要将所有列向上滚动,以便您的 DBMS 知道如何处理每个列。如果您尝试仅按 col1 进行分组,您的 DBMS 将出现错误,因为您没有告诉它如何处理 col2 和 col3 中的额外数据:

select col1, col2, col3 from table where col3='200' group by col1 --Errors

+----------+-------------+-------+
| col1     | col2        | col3  |
+----------+-------------+-------+
| 1        | some text 1 | 200   |
| 2        | some text 1 | 200   |
| 5        | some text 1 | 200   |
| ?        | some text 1?| 200?  |
+----------+-------------+-------+

如果您按所有 3 个分组,您的 DBMS 知道将整行分组(这是您想要的),并且只会显示一次重复的行:

select col1, col2, col3 from table where col3='200' group by col1, col2, col3

+----------+-------------+-------+
| col1     | col2        | col3  |
+----------+-------------+-------+
| 1        | some text 1 | 200   |
| 2        | some text 1 | 200   | --Desired results
| 5        | some text 1 | 200   |
+----------+-------------+-------+

与id

如果您想查看id,您必须告诉您的DBMS 要显示哪个id。即使我们按所有列分组,您也不会得到您想要的结果,因为 id 列会使每一行都不同(它们将不再组合在一起):

select id, col1, col2, col3 from table where col3='200' group by id, col1, col2, col3

+--------+----------+-------------+-------+
| id     | col1     | col2        | col3  |
+--------+----------+-------------+-------+
| 2      | 1        | some text 1 | 200   | --id = 2
| 3      | 2        | some text 1 | 200   |
| 7      | 5        | some text 1 | 200   |
| 8      | 1        | some text 1 | 200   | --id = 8
+--------+----------+-------------+-------+

因此,为了对这些行进行分组,我们需要明确说明如何处理 ids。根据你想要的结果,你想选择id = 2,这是最小id,所以让我们使用MIN():

select MIN(id), col1, col2, col3 from table where col3='200' group by col1, col2, col3
--Note, MIN() is an aggregate function, so id need not be in the group by

返回你想要的结果(id):

+--------+----------+-------------+-------+
| id     | col1     | col2        | col3  |
+--------+----------+-------------+-------+
| 2      | 1        | some text 1 | 200   |
| 3      | 2        | some text 1 | 200   |
| 7      | 5        | some text 1 | 200   |
+--------+----------+-------------+-------+

最后的想法

这是你的两个麻烦行:

+--------+----------+-------------+-------+
| id     | col1     | col2        | col3  |
+--------+----------+-------------+-------+
| 2      | 1        | some text 1 | 200   |
| 8      | 1        | some text 1 | 200   |
+--------+----------+-------------+-------+

任何时候你点击这些,只要想想你希望每一列做什么,一次一个。每次进行分组或聚合时,您都需要处理所有列。

  • id,你只想看到id = 2,也就是MIN()
  • co1,你只想看到不同的值,所以GROUP BY
  • col2,你只想看到不同的值,所以GROUP BY
  • col3,你只想看到不同的值,所以GROUP BY

【讨论】:

  • 我已经更新了我的问题,你能看一下吗
  • @pro_newbie 更新了我的答案。这是每个人都以不同方式学习的概念性东西。我试图用几种不同的方式来解释它。希望它有所帮助。
  • 感谢您的详细解释。我现在对它有了更多的了解。还有一件事,如果所有 col2 的值也彼此不同,那么您在Without id 部分中解释的内容将不起作用。它会给我所有的记录。如何处理这种情况?
  • @pro_newbie 在这种情况下,您必须决定如何处理col2。您的选择是 1.) 不要选择它。 2.)按它分组,但接受行不会合并的事实。 (但是,是的,在您的假设中,他们根本不会分组......) 3.)使用聚合仅显示您想要的那个(例如 MIN(),就像我们在 with id 部分中使用 id 所做的那样)
  • 很好的答案!一步一步深入问题的本质。
【解决方案2】:

也许你需要分析函数

像这样尝试:

select col1, col2, col3, col4, col5 
, sum(*) over (partition by col1) as col1_summary
, count(*) over () as total_count
from t1 

如果你用谷歌搜索这篇文章 - 你会发现成千上万的例子 例如这个 Introduction to Analytic Functions (Part 1)

【讨论】:

    【解决方案3】:

    为什么要 GROUP BY ,而不是 ORDER BY ?

    如果您说明您要解决的问题的英文版本(即要求),则更具体会更容易。

    【讨论】:

      【解决方案4】:

      我猜,也许你需要 upivot 函数

      或发布您想要的具体最终结果

      select  col3, col_group 
      from table
      UNPIVOT ( col_group for value in ( col1,col2,col4,col5)) 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-01-02
        • 1970-01-01
        • 2023-03-10
        • 2017-03-05
        • 2011-08-30
        • 1970-01-01
        相关资源
        最近更新 更多