是否有将多行聚合为一行的 Oracle SQL 查询?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1120706/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-01 02:47:09  来源:igfitidea点击:

Is there an Oracle SQL query that aggregates multiple rows into one row?

sqloracleaggregationstring-concatenation

提问by user128807

I have a table that looks like this:

我有一张看起来像这样的表:

A 1 
A 2 
B 1 
B 2

And I want to produce a result set that looks like this:

我想生成一个如下所示的结果集:

A 1 2 
B 1 2

Is there a SQL statement that will do this? I am using Oracle.

是否有执行此操作的 SQL 语句?我正在使用甲骨文。

Related questions:

相关问题:

回答by John Hyland

It depends on the version of Oracle you're using. If it supports the wm_concat() function, then you can simply do something like this:

这取决于您使用的 Oracle 版本。如果它支持 wm_concat() 函数,那么您可以简单地执行以下操作:

SELECT field1, wm_concat(field2) FROM YourTable GROUP BY field2;

wm_concat() basically works just like group_concat()in MySQL. It may not be documented, so fire up ye olde sqlplus and see if it's there.

wm_concat() 基本上就像MySQL 中的group_concat()一样。它可能没有记录在案,所以启动 ye olde sqlplus 看看它是否在那里。

If it isn'tthere, then you'll want to implement something equivalent yourself. You can find some instructions on how to do this in the string aggregation pageat oracle-base.com.

如果它存在,那么您将需要自己实现一些等效的东西。您可以在 oracle-base.com的字符串聚合页面中找到有关如何执行此操作的一些说明。

回答by user1973071

Pretty old topic, but it could help others since Oracle improved in the mean time.

很老的话题,但它可以帮助其他人,因为 Oracle 同时改进了。

The LISTAGGfunction is what you are looking for (in 11g at least)

LISTAGG功能是你在找什么(在11g中至少)

回答by Quassnoi

In Oracle 10g+:

Oracle 10g+

SELECT  *
FROM    (
        SELECT  *
        FROM    mytable
        MODEL
        PARTITION BY
                (grouper)
        DIMENSION BY
                (ROW_NUMBER() OVER (PARTITION BY grouper ORDER BY id) AS rn)
        MEASURES
                (val, val AS group_concat, 0 AS mark)
        RULES SEQUENTIAL ORDER (
                group_concat[rn > 1] ORDER BY rn = group_concat[CV() - 1] || ', ' || val[CV()],
                mark[ANY] ORDER BY rn = PRESENTV(mark[CV() + 1], 0, 1)
                )
        )
WHERE   mark = 1
ORDER BY
        grouper

See this article in my blog for explanations:

有关解释,请参阅我博客中的这篇文章:

回答by Mac

Try something like :

尝试类似:

SELECT
    field1,
    RTRIM(REPLACE(REPLACE(XMLAgg(XMLElement("x", field2) ORDER BY field2), '<x>'), '</x>', ' ')) AS field2s
  FROM yourTable
  GROUP BY field1

Freely inspired by an answer found in this Oracle forum.

受到此 Oracle 论坛中的答案的自由启发。

EDIT:this solution proved veryresources intensive with requests involving something like 105rows. I ended up replacing this by custom aggregate functions as suggested by John.

编辑:这个解决方案被证明是非常资源密集型的,请求涉及 10 5行。我最终按照John 的建议用自定义聚合函数替换了它。

回答by hsuk

If you have got 10g, then you have to go through the function below:

如果您有10g,那么您必须通过以下功能:

CREATE OR REPLACE FUNCTION get_separated_value (input_val  in  number)
  RETURN VARCHAR2
IS
  return_text  VARCHAR2(10000) := NULL;
BEGIN
  FOR x IN (SELECT col2 FROM table_name WHERE col1 = input_val) LOOP
    return_text := return_text || ' ' || x.col2 ;
  END LOOP;
  RETURN return_text;
END;
/

So, you can do like:

所以,你可以这样做:

select col1, get_separated_value(col1) from table_name

Fiddle here

在这里摆弄

If you have got oracle 11g, you can use listagg:

如果你有 oracle 11g,你可以使用listagg

SELECT 
    age,
    LISTAGG(name, ' ') WITHIN GROUP (ORDER BY name) "names"
FROM table_x
GROUP BY age

Fiddle here for Listagg

在这里为 Listagg 摆弄

回答by haki

SELECT a , COLLECT(b) FROM foo GROUP BY a

very useful when used in pl/sql - can be casted to a user defined collection.

在 pl/sql 中使用时非常有用 - 可以转换为用户定义的集合。

回答by jva

User defined aggregate functions: http://www.adp-gmbh.ch/ora/sql/user_def_agg.html

用户定义的聚合函数:http: //www.adp-gmbh.ch/ora/sql/user_def_agg.html

Just copy/paste and use it. Works on 9i.

只需复制/粘贴并使用它。适用于 9i。