如何使用SQL统计组的出现次数,并将两个不同的列视为未排序的集合?

如何使用SQL统计组的出现次数,并将两个不同的列视为未排序的集合?,sql,oracle11g,Sql,Oracle11g,根据表格: CREATE TABLE foo ( thing_a VARCHAR2(15), thing_b VARCHAR2(15) ); 那排呢 INSERT INTO foo (thing_a, thing_b) VALUES 'red', 'green'; INSERT INTO foo (thing_a, thing_b) VALUES 'red', 'green'; INSERT INTO foo (thing_a, thing_b) VALUES 'green',

根据表格:

CREATE TABLE foo (
    thing_a VARCHAR2(15),
    thing_b VARCHAR2(15)
);
那排呢

INSERT INTO foo (thing_a, thing_b) VALUES 'red', 'green';
INSERT INTO foo (thing_a, thing_b) VALUES 'red', 'green';
INSERT INTO foo (thing_a, thing_b) VALUES 'green', 'red';
INSERT INTO foo (thing_a, thing_b) VALUES 'red', 'blue';
我想知道结果

green,red: 3
blue,red: 1
换言之,我想对每一组的发生情况进行统计,但我想把“红色”和“绿色”看作“绿色”和“红色”。 我找到的最接近“解决方案”是:

因此,它正确地进行分组,但不计算任何内容


关于如何解决这个问题,有什么建议吗?

你就快到了。只需将
案例
查询包装在派生表中,然后
按其结果分组:

select thing, count(*)
from
(
    SELECT CASE WHEN thing_a < thing_b THEN thing_a || thing_b
           ELSE thing_b || thing_a
           END as thing
    FROM foo
) dt
group by thing
select ta, tb, count(*)
from
(
    select thing_a as ta, thing_b as tb from foo where thing_a <= thing_b
    union all
    select thing_b, thing_a from foo where thing_a > thing_b
) dt
group by ta, tb

符合ANSI SQL标准且可移植

这可以在单个
SELECT
语句中完成-按最小值、最大值分组。注意:如果任一列中可能存在
null
,则此操作无效;如果这是可能的,那么在编写查询时必须更加小心地处理它

with
     foo ( thing_a, thing_b ) as (
       select 'red'  , 'green' from dual union all
       select 'red'  , 'green' from dual union all
       select 'green', 'red'   from dual union all
       select 'red'  , 'blue'  from dual union all
       select 'ab'   , 'cde'   from dual union all
       select 'abcd' , 'e'     from dual union all
       select 'cde'  , 'ab'    from dual
     )
-- end of test data; SQL query begins BELOW THIS LINE
select least(thing_a, thing_b) as thing_a, greatest(thing_a, thing_b) as thing_b,
       count(*) as cnt
from   foo
group by least(thing_a, thing_b), greatest(thing_a, thing_b)
order by thing_a, thing_b   --   if needed
;

THING_A THING_B CNT
------- ------- ---
ab      cde       2
abcd    e         1
blue    red       1
green   red       3

4 rows selected.

@我看到你把这个答案标记为“正确”,考虑到你的经验,这是令人惊讶的。假设您的数据中有以下无序集:
('ab','cde')
('abcd','e')
。这个解决方案将把它们当作一样对待。@mathguy,哎呀。。。我能说什么。。。在a和b之间添加逗号似乎是一个简单的编辑。请稍后再试。如果字符串本身包含逗号,这将不起作用。@mathguy,我知道,但OP在示例数据中没有逗号或其他奇数字符。无论如何,上一个UNION ALL/GROUP BY查询没有逗号问题。很好!我忘了提到我的数据符合
^A-Z$
(它们都是三个字母的大写代码),而我的实际解决方案最终实现了jarlh在这里提出的建议——添加逗号来分隔它们。这很有趣,我不知道你可以使用分组方式中的函数!我的数据中没有空值,所以这可以正常工作。
select thing, count(*)
from
(
    SELECT CASE WHEN thing_a < thing_b THEN thing_a || ', ' || thing_b
           ELSE thing_b || ', ' || thing_a
           END as thing
    FROM foo
) dt
group by thing
select ta, tb, count(*)
from
(
    select thing_a as ta, thing_b as tb from foo where thing_a <= thing_b
    union all
    select thing_b, thing_a from foo where thing_a > thing_b
) dt
group by ta, tb
with
     foo ( thing_a, thing_b ) as (
       select 'red'  , 'green' from dual union all
       select 'red'  , 'green' from dual union all
       select 'green', 'red'   from dual union all
       select 'red'  , 'blue'  from dual union all
       select 'ab'   , 'cde'   from dual union all
       select 'abcd' , 'e'     from dual union all
       select 'cde'  , 'ab'    from dual
     )
-- end of test data; SQL query begins BELOW THIS LINE
select least(thing_a, thing_b) as thing_a, greatest(thing_a, thing_b) as thing_b,
       count(*) as cnt
from   foo
group by least(thing_a, thing_b), greatest(thing_a, thing_b)
order by thing_a, thing_b   --   if needed
;

THING_A THING_B CNT
------- ------- ---
ab      cde       2
abcd    e         1
blue    red       1
green   red       3

4 rows selected.