给出4张表,每个表包含项目并代表一组,如何获得绘制维恩图所需的每个隔间中的项目计数,如下所示。计算应该在mysql服务器上进行,避免将项传输到应用服务器。
示例表:
s1: s2: s3: s4:
+------+ +------+ +------+ +------+
| item | | item | | item | | item |
+------+ +------+ +------+ +------+
| a | | a | | a | | a |
+------+ +------+ +------+ +------+
| b | | b | | b | | c |
+------+ +------+ +------+ +------+
| c | | c | | d | | d |
+------+ +------+ +------+ +------+
| d | | e | | e | | e |
+------+ +------+ +------+ +------+
| ... | | ... | | ... | | ... |
现在,我想我会计算一些设定的幂。一些例子 I
对应 s1
, II
至 s2
, III
至 s3
以及 IV
至 s4
:
如果我重新解释 sx
作为一个集合,我会写: |s1 ∩ s2 ∩ s3 ∩ s4|
-中间的白色25 |(s1 ∩ s2 ∩ s4) \ s3|
-相对于中心,右下方的白色15 |(s1 ∩ s4) \ (s2 ∪ s3)|
-底部的白色5 |s1 \ (s2 ∪ s3 ∪ s4)|
-蓝色地面上的深蓝色60
... 直到15岁。
如何在mysql服务器上高效地计算这些功率?mysql是否提供了一个帮助计算的函数?
一种简单的方法是运行1的查询。
SELECT count(*) FROM(
SELECT item FROM s1
INTERSECT
SELECT item FROM s2
INTERSECT
SELECT item FROM s3
INTERSECT
SELECT item FROM s4);
另一个查询是2。
SELECT count(*) FROM(
SELECT item FROM s1
INTERSECT
SELECT item FROM s2
INTERSECT
SELECT item FROM s4
EXCEPT
SELECT item FROM s3);
以此类推,产生15个查询。
3条答案
按热度按时间ar7v8xwq1#
这个问题有点复杂,所以答案很简单。让我解释一下k.t.的答案
这个
universe
结果是所有表的并集(消除了重复项),类似于然后,s1、s2、s3和s4接合
并转换为二进制字符串(0:如果单元格为空;1:否则)打电话来了
Region
其中第一个数字对应于s1,第二个数字对应于s2,依此类推最后按地区进行汇总和分组
请注意,其中包含0个集合元素的区域不会显示在结果和
0000
永远不会(=项目不是任何集合s1、s2、s3、s4的一部分)因此有15个区域。ny6fqffe2#
以下程序:
创建了一个存储过程,该过程创建包含集合的临时内存表。
请注意,mysql不允许您在查询中多次引用内存中的临时表。
如前所述,mysql没有
INTERSECT
或者EXCEPT
. 但你可以模仿他们。通过从原始数据/原始集中删除重复项,仿真可以更加简化。决定将计算出的值存储到一个变量中,每个变量输出一个表,表中包含与组件对应的所有15个值。
我现在想到的是https://gist.github.com/rillke/c2da0921f8f2a047615f41fab8781c11
wgmfuz8q3#
尝试以下操作:
免责声明:我只在sqlite中测试过这个。你可能需要
SET sql_mode='PIPES_AS_CONCAT'
对于在mysql中工作的ansi字符串连接,或者使用concat
而不是功能。这个WITH
只有mysql的8.0版本才支持语法,但是您可以适当地使用临时表或嵌套查询。如果集合非常大,您可能需要索引
item
列,以防sql优化器无法自己找到它。