Oracle聚合函数以及如何连接列中的所有值

时间:2014-03-01 08:15:09

标签: sql oracle max concatenation aggregate

所有

我的Oracle数据库是10g企业版10.2.0.5.0版--64位

我有以下声明,它有效地获得了每种情况下的最大值(或最小值或计数等)值,但是我想要的是获取并连接所有值而不是最大值,最小值或计数值 - 请问这是一种优雅的方式吗?

SELECT lla.id, 
       max(decode(lla.attrid, 2, lla.valstr, null)) "Attribute Name 2",
       min(decode(lla.attrid, 3, lla.valstr, null)) "Attribute Name 3",
       count(decode(lla2.attrid, 5, lla2.valstr, null)) "Attribute Name 5"
FROM llattrdata lla, llattrdata lla2
WHERE lla.id = lla2.id 
      AND lla.defid = 111111 --category id 1
      AND lla2.defid = 222222 --category id 2
      AND lla.id = 48212327 and lla2.id = 48212327
      GROUP BY lla.id

希望行看起来像这样:

12121212 | fred, jack, gill | 56 | 29,10

更清楚的是,'属性名称3'(例如)包含的值我希望看到的全部而不仅仅是最大值或最小值。换句话说,对于该属性,我可以获得最大值或最小值,甚至计数,但是无法看到获取所有值的方法?换句话说,我可以得到10作为最小值,29作为最大值 - 甚至2作为计数但不是29和10在同一列中!

非常感谢,

4 个答案:

答案 0 :(得分:2)

SELECT e.department_id,
       listagg(e.first_name) within group (order by e.department_id) "Attribute Name 2"
FROM employees e join
     departments d
     on e.department_id = d.department_id 
GROUP BY e.department_id;

您可以使用上面的示例并更改您的查询

答案 1 :(得分:0)

使用wmsys.wm_concat函数learn more here。这是Oracle 10中未记录的功能。

它返回以逗号分隔的列表,您可以使用replace函数将逗号替换为您需要的内容。

不幸的是,此函数没有order子句,因此您无法在列表中指定顺序。

修改

只要您无法使用此功能,您只需创建它:

CREATE OR REPLACE TYPE wm_concat_impl
   AUTHID CURRENT_USER
AS OBJECT (
   curr_str   VARCHAR2 (32767),
   STATIC FUNCTION odciaggregateinitialize (sctx IN OUT wm_concat_impl)
      RETURN NUMBER,
   MEMBER FUNCTION odciaggregateiterate (
      SELF   IN OUT   wm_concat_impl,
      p1     IN       VARCHAR2
   )
      RETURN NUMBER,
   MEMBER FUNCTION odciaggregateterminate (
      SELF          IN       wm_concat_impl,
      returnvalue   OUT      VARCHAR2,
      flags         IN       NUMBER
   )
      RETURN NUMBER,
   MEMBER FUNCTION odciaggregatemerge (
      SELF    IN OUT   wm_concat_impl,
      sctx2   IN       wm_concat_impl
   )
      RETURN NUMBER
);
/

CREATE OR REPLACE TYPE BODY wm_concat_impl
IS
   STATIC FUNCTION odciaggregateinitialize (sctx IN OUT wm_concat_impl)
      RETURN NUMBER
   IS
   BEGIN
      sctx := wm_concat_impl (NULL);
      RETURN odciconst.success;
   END;
   MEMBER FUNCTION odciaggregateiterate (
      SELF   IN OUT   wm_concat_impl,
      p1     IN       VARCHAR2
   )
      RETURN NUMBER
   IS
   BEGIN
      IF (curr_str IS NOT NULL)
      THEN
         curr_str := curr_str || ',' || p1;
      ELSE
         curr_str := p1;
      END IF;

      RETURN odciconst.success;
   END;
   MEMBER FUNCTION odciaggregateterminate (
      SELF          IN       wm_concat_impl,
      returnvalue   OUT      VARCHAR2,
      flags         IN       NUMBER
   )
      RETURN NUMBER
   IS
   BEGIN
      returnvalue := curr_str;
      RETURN odciconst.success;
   END;
   MEMBER FUNCTION odciaggregatemerge (
      SELF    IN OUT   wm_concat_impl,
      sctx2   IN       wm_concat_impl
   )
      RETURN NUMBER
   IS
   BEGIN
      IF (sctx2.curr_str IS NOT NULL)
      THEN
         SELF.curr_str := SELF.curr_str || ',' || sctx2.curr_str;
      END IF;

      RETURN odciconst.success;
   END;
END;
/

CREATE OR REPLACE FUNCTION wm_concat (p1 VARCHAR2)
   RETURN VARCHAR2
   AGGREGATE USING wm_concat_impl;
/

查询来自this website,不幸的是,它是俄语的,但只是为了您的目的使用此自定义聚合函数。

答案 2 :(得分:0)

试试这个:

SELECT lla.id || ' | ' ||
       max(decode(lla.attrid, 2, lla.valstr, null)) || ' | ' ||
       min(decode(lla.attrid, 3, lla.valstr, null)) || ' | ' ||
       count(decode(lla2.attrid, 5, lla2.valstr, null))
FROM llattrdata lla, llattrdata lla2
WHERE lla.id = lla2.id 
      AND lla.defid = 111111 --category id 1
      AND lla2.defid = 222222 --category id 2
      AND lla.id = 48212327 and lla2.id = 48212327
      GROUP BY lla.id

答案 3 :(得分:0)

我遇到了同样的问题,并使用了由Tom Kyte创建的STRAGG(如在STRING AGGregate中)。

https://asktom.oracle.com/pls/asktom/f?p=100:11:::::P11_QUESTION_ID:15637744429336

create or replace type stragg_type as object
(
  string varchar2(4000),
  static function ODCIAggregateInitialize
    ( sctx in out stragg_type )
    return number ,
  member function ODCIAggregateIterate
    ( self  in out stragg_type ,
      value in     varchar2
    ) return number ,
  member function ODCIAggregateTerminate
    ( self        in  stragg_type,
      returnvalue out varchar2,
      flags in number
    ) return number ,
  member function ODCIAggregateMerge
    ( self in out stragg_type,
      ctx2 in     stragg_type
    ) return number
);
/

create or replace type body stragg_type
is
  static function ODCIAggregateInitialize
  ( sctx in out stragg_type )
  return number
  is
  begin
    sctx := stragg_type( null ) ;
    return ODCIConst.Success ;
  end;
  member function ODCIAggregateIterate
  ( self  in out stragg_type ,
    value in     varchar2
  ) return number
  is
  begin
    self.string := self.string || ',' || value ;
    return ODCIConst.Success;
  end;
  member function ODCIAggregateTerminate
  ( self        in  stragg_type ,
    returnvalue out varchar2 ,
    flags       in  number
  ) return number
  is
  begin
    returnValue := ltrim( self.string, ',' );
    return ODCIConst.Success;
  end;
  member function ODCIAggregateMerge
  ( self in out stragg_type ,
    ctx2 in     stragg_type
  ) return number
  is
  begin
    self.string := self.string || ctx2.string;
    return ODCIConst.Success;
  end;
end;
/

create or replace function stragg
  ( input varchar2 )
  return varchar2
  deterministic
  parallel_enable
  aggregate using stragg_type
;
/

在sqlplus或sqldev中依次运行三个create语句。现在,在用户模式中创建了stragg()函数。然后你可以这样做:

SELECT lla.id, 
       max(decode(lla.attrid, 2, lla.valstr, null)) "Attribute Name 2",
       STRAGG(decode(lla.attrid, 3, lla.valstr, null)) "Attribute Name 3 List",
       count(decode(lla2.attrid, 5, lla2.valstr, null)) "Attribute Name 5"
FROM llattrdata lla, llattrdata lla2
WHERE lla.id = lla2.id 
      AND lla.defid = 111111 --category id 1
      AND lla2.defid = 222222 --category id 2
      AND lla.id = 48212327 and lla2.id = 48212327
GROUP BY lla.id