计算组间重叠
Calculating overlap between groups
我有一个 table,其中包含两个感兴趣的列,item_id
和 bucket_id
。 bucket_id
有固定数量的值,如果需要,我可以列出它们。
每个 item_id
可以出现多次,但每次出现都会有一个单独的 bucket_id
值。例如,123
的item_id
可以在table中出现两次,一次在[=20=的bucket_id
下,一次在B
下。
我的目标是确定每对 bucket_id
值之间存在多少重叠并将其显示为 N×N 矩阵。
例如,考虑下面的小例子table:
item_id bucket_id
========= ===========
111 A
111 B
111 C
222 B
222 D
333 A
333 C
444 C
所以对于这个数据集,桶 A
和 B
有一个共同点 item_id
,桶 C
和 D
没有共同点,等等
我想将上面的 table 格式化成如下格式:
A B C D
===================================
A 2 1 2 0
B 1 2 1 1
C 2 1 3 0
D 0 1 0 1
在上面的 table 中,行和列的交集告诉您两个 bucket_id
值中存在多少条记录。例如,在 A
行与 C
列相交的地方,我们有一个 2
,因为在 bucket_id
A 和 C 中都存在 2 条记录。因为交集X 和 Y 与 Y 和 X 的交集相同,上面的 table 在对角线上镜像。
我想该查询涉及一个 PIVOT
,但我终究无法弄清楚如何让它工作。
我相信这应该能为您提供所需的数据。然后可以通过编程方式(或在 Excel 等中)对 table 进行旋转。
-- This gets the distinct pairs of buckets
select distinct
a.name,
b.name
from
bucket a
join bucket b
where
a.name < b.name
order by
a.name,
b.name
+ --------- + --------- +
| name | name |
+ --------- + --------- +
| A | B |
| A | C |
| A | D |
| B | C |
| B | D |
| C | D |
+ --------- + --------- +
6 rows
-- This gets the distinct pairs of buckets with the counts you are looking for
select distinct
a.name,
b.name,
count(distinct bi.item_id)
from
bucket a
join bucket b
left outer join bucket_item ai on ai.bucket_name = a.name
left outer join bucket_item bi on bi.bucket_name = b.name and ai.item_id = bi.item_id
where
a.name < b.name
group by
a.name,
b.name
order by
a.name,
b.name
+ --------- + --------- + ------------------------------- +
| name | name | count(distinct bi.item_id) |
+ --------- + --------- + ------------------------------- +
| A | B | 2 |
| A | C | 1 |
| A | D | 0 |
| B | C | 2 |
| B | D | 0 |
| C | D | 0 |
+ --------- + --------- + ------------------------------- +
6 rows
这是包含 DDL 的完整示例并插入内容以进行设置(这在 mysql 中,但同样的想法也适用于其他地方):
use example;
drop table if exists bucket;
drop table if exists item;
drop table bucket_item;
create table bucket (
name varchar(1)
);
create table item(
id int
);
create table bucket_item(
bucket_name varchar(1) references bucket(name),
item_id int references item(id)
);
insert into bucket values ('A');
insert into bucket values ('B');
insert into bucket values ('C');
insert into bucket values ('D');
insert into item values (111);
insert into item values (222);
insert into item values (333);
insert into item values (444);
insert into item values (555);
insert into bucket_item values ('A',111);
insert into bucket_item values ('A',222);
insert into bucket_item values ('A',333);
insert into bucket_item values ('B',222);
insert into bucket_item values ('B',333);
insert into bucket_item values ('B',444);
insert into bucket_item values ('C',333);
insert into bucket_item values ('C',444);
insert into bucket_item values ('D',555);
-- query to get distinct pairs of buckets
select distinct
a.name,
b.name
from
bucket a
join bucket b
where
a.name < b.name
order by
a.name,
b.name
;
select distinct
a.name,
b.name,
count(distinct bi.item_id)
from
bucket a
join bucket b
left outer join bucket_item ai on ai.bucket_name = a.name
left outer join bucket_item bi on bi.bucket_name = b.name and ai.item_id = bi.item_id
where
a.name < b.name
group by
a.name,
b.name
order by
a.name,
b.name
;
您可以使用简单的 PIVOT:
SELECT t1.bucket_id,
SUM( CASE WHEN t2.bucket_id = 'A' THEN 1 ELSE 0 END ) AS A,
SUM( CASE WHEN t2.bucket_id = 'B' THEN 1 ELSE 0 END ) AS B,
SUM( CASE WHEN t2.bucket_id = 'C' THEN 1 ELSE 0 END ) AS C,
SUM( CASE WHEN t2.bucket_id = 'D' THEN 1 ELSE 0 END ) AS D
FROM table1 t1
JOIN table1 t2 ON t1.item_id = t2.item_id
GROUP BY t1.bucket_id
ORDER BY 1
;
或者您可以使用 Oracle PIVOT 子句(适用于 11.2 及更高版本):
SELECT * FROM (
SELECT t1.bucket_id AS Y_bid,
t2.bucket_id AS x_bid
FROM table1 t1
JOIN table1 t2 ON t1.item_id = t2.item_id
)
PIVOT (
count(*) FOR x_bid in ('A','B','C','D')
)
ORDER BY 1
;
我有一个 table,其中包含两个感兴趣的列,item_id
和 bucket_id
。 bucket_id
有固定数量的值,如果需要,我可以列出它们。
每个 item_id
可以出现多次,但每次出现都会有一个单独的 bucket_id
值。例如,123
的item_id
可以在table中出现两次,一次在[=20=的bucket_id
下,一次在B
下。
我的目标是确定每对 bucket_id
值之间存在多少重叠并将其显示为 N×N 矩阵。
例如,考虑下面的小例子table:
item_id bucket_id
========= ===========
111 A
111 B
111 C
222 B
222 D
333 A
333 C
444 C
所以对于这个数据集,桶 A
和 B
有一个共同点 item_id
,桶 C
和 D
没有共同点,等等
我想将上面的 table 格式化成如下格式:
A B C D
===================================
A 2 1 2 0
B 1 2 1 1
C 2 1 3 0
D 0 1 0 1
在上面的 table 中,行和列的交集告诉您两个 bucket_id
值中存在多少条记录。例如,在 A
行与 C
列相交的地方,我们有一个 2
,因为在 bucket_id
A 和 C 中都存在 2 条记录。因为交集X 和 Y 与 Y 和 X 的交集相同,上面的 table 在对角线上镜像。
我想该查询涉及一个 PIVOT
,但我终究无法弄清楚如何让它工作。
我相信这应该能为您提供所需的数据。然后可以通过编程方式(或在 Excel 等中)对 table 进行旋转。
-- This gets the distinct pairs of buckets
select distinct
a.name,
b.name
from
bucket a
join bucket b
where
a.name < b.name
order by
a.name,
b.name
+ --------- + --------- +
| name | name |
+ --------- + --------- +
| A | B |
| A | C |
| A | D |
| B | C |
| B | D |
| C | D |
+ --------- + --------- +
6 rows
-- This gets the distinct pairs of buckets with the counts you are looking for
select distinct
a.name,
b.name,
count(distinct bi.item_id)
from
bucket a
join bucket b
left outer join bucket_item ai on ai.bucket_name = a.name
left outer join bucket_item bi on bi.bucket_name = b.name and ai.item_id = bi.item_id
where
a.name < b.name
group by
a.name,
b.name
order by
a.name,
b.name
+ --------- + --------- + ------------------------------- +
| name | name | count(distinct bi.item_id) |
+ --------- + --------- + ------------------------------- +
| A | B | 2 |
| A | C | 1 |
| A | D | 0 |
| B | C | 2 |
| B | D | 0 |
| C | D | 0 |
+ --------- + --------- + ------------------------------- +
6 rows
这是包含 DDL 的完整示例并插入内容以进行设置(这在 mysql 中,但同样的想法也适用于其他地方):
use example;
drop table if exists bucket;
drop table if exists item;
drop table bucket_item;
create table bucket (
name varchar(1)
);
create table item(
id int
);
create table bucket_item(
bucket_name varchar(1) references bucket(name),
item_id int references item(id)
);
insert into bucket values ('A');
insert into bucket values ('B');
insert into bucket values ('C');
insert into bucket values ('D');
insert into item values (111);
insert into item values (222);
insert into item values (333);
insert into item values (444);
insert into item values (555);
insert into bucket_item values ('A',111);
insert into bucket_item values ('A',222);
insert into bucket_item values ('A',333);
insert into bucket_item values ('B',222);
insert into bucket_item values ('B',333);
insert into bucket_item values ('B',444);
insert into bucket_item values ('C',333);
insert into bucket_item values ('C',444);
insert into bucket_item values ('D',555);
-- query to get distinct pairs of buckets
select distinct
a.name,
b.name
from
bucket a
join bucket b
where
a.name < b.name
order by
a.name,
b.name
;
select distinct
a.name,
b.name,
count(distinct bi.item_id)
from
bucket a
join bucket b
left outer join bucket_item ai on ai.bucket_name = a.name
left outer join bucket_item bi on bi.bucket_name = b.name and ai.item_id = bi.item_id
where
a.name < b.name
group by
a.name,
b.name
order by
a.name,
b.name
;
您可以使用简单的 PIVOT:
SELECT t1.bucket_id,
SUM( CASE WHEN t2.bucket_id = 'A' THEN 1 ELSE 0 END ) AS A,
SUM( CASE WHEN t2.bucket_id = 'B' THEN 1 ELSE 0 END ) AS B,
SUM( CASE WHEN t2.bucket_id = 'C' THEN 1 ELSE 0 END ) AS C,
SUM( CASE WHEN t2.bucket_id = 'D' THEN 1 ELSE 0 END ) AS D
FROM table1 t1
JOIN table1 t2 ON t1.item_id = t2.item_id
GROUP BY t1.bucket_id
ORDER BY 1
;
或者您可以使用 Oracle PIVOT 子句(适用于 11.2 及更高版本):
SELECT * FROM (
SELECT t1.bucket_id AS Y_bid,
t2.bucket_id AS x_bid
FROM table1 t1
JOIN table1 t2 ON t1.item_id = t2.item_id
)
PIVOT (
count(*) FOR x_bid in ('A','B','C','D')
)
ORDER BY 1
;