如何使用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.