1

假设下表:

表A:

ID  GroupName SomeValue
1   C         1
2   C         1
2   B         1
2   A         1

我需要构建一个选择以下结果的查询:

ID  GroupName SomeValue
1   C         1
1   B         0
1   A         0
2   C         1
2   B         1
2   A         1

GroupName 实际上是从 TableA 列的 CASE 表达式派生的,只能取 3 个值:A、B、C。

分析函数是要走的路吗?

编辑

抱歉,没有提及,但 ID 可能包含多列。考虑这个例子:

ID1 ID2 GroupName SomeValue
1   1   C         1

1   2   C         1

2   2   C         1
2   2   B         1
2   2   A         1

我需要SomeValue为每个唯一的组合 ID1+ID2 填充 0。所以结果应该是这样的:

ID1 ID2 GroupName SomeValue

1   1   C         1
1   1   B         0
1   1   A         0

1   2   C         1
1   2   B         0
1   2   A         0

2   2   C         1
2   2   B         1
2   2   A         1  

EDIT2
似乎是@Laurence 提出的解决方案,即使对于多列“ID”也应该有效。我无法重写@Nicholas Krasnov 提出的查询以符合此要求。但是有人可以比较这些解决方案的性能吗?工作会analytic function比“交叉连接+左外连接”更快吗?

4

2 回答 2

3

partition by为了填补空白,您可以使用外连接子句编写类似的查询:

SQL> with t1(ID,GroupName,SomeValue) as
  2  (
  3    select 1,   'C',   1  from dual union all
  4    select 2,   'C',   1  from dual union all
  5    select 2,   'B',   1  from dual union all
  6    select 2,   'A',   1  from dual
  7  ),
  8  groups(group_name) as(
  9    select 'A' from dual union all
 10    select 'B' from dual union all
 11    select 'C' from dual
 12  )
 13  select t1.ID
 14       , g.group_name
 15       , nvl(SomeValue, 0) SomeValue
 16    from t1
 17    partition by (t1.Id)
 18    right outer join groups g
 19       on (t1.GroupName = g.group_name)
 20    order by t1.ID asc, g.group_name desc
 21  ;

        ID GROUP_NAME  SOMEVALUE
---------- ---------- ----------
         1 C                   1
         1 B                   0
         1 A                   0
         2 C                   1
         2 B                   1
         2 A                   1

6 rows selected

更新:对评论的回应。

还要在子句中指定ID2列:partition by

SQL> with t1(ID1, ID2, GroupName,SomeValue) as
  2  (
  3    select 1, 1, 'C', 1 from dual union all
  4    select 1, 2, 'C', 1 from dual union all
  5    select 2, 2, 'C', 1  from dual union all
  6    select 2, 2, 'B', 1  from dual union all
  7    select 2, 2, 'A', 1  from dual
  8  ),
  9  groups(group_name) as(
 10    select 'A' from dual union all
 11    select 'B' from dual union all
 12    select 'C' from dual
 13  )
 14  select t1.ID1
 15       , t1.ID2
 16       , g.group_name
 17       , nvl(SomeValue, 0) SomeValue
 18    from t1
 19    partition by (t1.Id1, t1.Id2)
 20    right outer join groups g
 21    on (t1.GroupName = g.group_name)
 22  order by t1.ID1, t1.ID2  asc , g.group_name desc
 23  ;

       ID1        ID2 GROUP_NAME  SOMEVALUE
---------- ---------- ---------- ----------
         1          1 C                   1
         1          1 B                   0
         1          1 A                   0
         1          2 C                   1
         1          2 B                   0
         1          2 A                   0
         2          2 C                   1
         2          2 B                   1
         2          2 A                   1

9 rows selected
于 2012-11-02T10:50:11.923 回答
1
Select
  i.Id1,
  i.Id2,
  g.GroupName,
  Coalesce(a.SomeValue, 0) As SomeValue
From
  (select distinct ID1, ID2 from TableA) as i
    cross join
  (select distinct GroupName from TableA) as g
    left outer join
  tableA a
    on i.ID = a.ID and g.GroupName = a.GroupName
Order By
  1,
  2,
  3 Desc
于 2012-11-02T10:52:03.600 回答