我想在MySQL或postgres中进行查询,这些查询将从4个表中生成。
请参阅下表。
我想在下面定义的矩阵表中使用postgres或sql查询。
如何使用SQL实现此目的?
提前多多谢谢你。
表:目标
+----+-------------+
| id | name |
+----+-------------+
| 1 | 9999999991 |
| 2 | 9999999992 |
| 3 | 9999999993 |
| 4 | 9999999994 |
| 5 | 9999999995 |
| 6 | 9999999996 |
| 7 | 9999999997 |
| 8 | 9999999998 |
+----+-------------+
表:Target_groups
+----+-------------+
| id | name |
+----+-------------+
| 1 | Group 1 |
| 2 | Group 2 |
| 3 | Group 3 |
| 4 | Group 4 |
+----+-------------+
表格:Target_groups_map
+----+-----------+--------------+
| id |targets | target_groups|
+----+-----------+--------------+
| 1 | 9999999991| 1 |
| 2 | 9999999992| 1 |
| 3 | 9999999993| 2 |
| 4 | 9999999994| 2 |
| 5 | 9999999995| 3 |
| 6 | 9999999996| 3 |
| 6 | 9999999997| 4 |
| 6 | 9999999998| 4 |
+----+-----------+--------------+
表:Call_details
+----+-----------+--------------+
| id | caller | called |
+----+-----------+--------------+
| 1 | 9999999995| 9999999996 |
| 2 | 9999999992| 9999999998 |
| 3 | 9999999993| 9999999998 |
| 4 | 9999999994| 9999999991 |
| 5 | 9999999995| 9999999998 |
| 6 | 9999999996| 9999999992 |
| 6 | 9999999991| 9999999993 |
| 6 | 9999999992| 9999999998 |
+----+-----------+--------------+
我想要的矩阵表
+--------+--------+--------+--------+--------+
| | Group 1| Group 2| Group 3| Group 4|
+--------+--------+--------+--------+--------+
| Group 1| - | 1 | - | 2 |
| Group 2| 1 | - | - | 1 |
| Group 3| 1 | - | 1 | 1 |
| Group 4| - | - | - | - |
+--------+--------+--------+--------+--------+
答案 0 :(得分:3)
在Postgres中,您需要扩展程序tablefunc
来生成 pivot 表:
<p>Regular text here</p>
<p class="rtl">Persian text here</p>
<p class="justify">Justified Regular text here</p>
<p class="rtl justify">Justified Persian text here</p>
create extension if not exists tablefunc;
的查询:
crosstab()
使用汇总函数string_agg()
代替select * from crosstab($$
select t1.name caller_name, t2.name called_name, count
from target_groups t1
cross join target_groups t2
left join (
select c1, c2, count(*)::int
from (
select g1.target_groups c1, g2.target_groups c2
from call_details c
join target_groups_map g1 on c.caller = g1.targets
join target_groups_map g2 on c.called = g2.targets
) c
group by 1, 2
order by 1, 2
) c
on t1.id = c1 and t2.id = c2
$$)
as ct (" " text, "Group 1" int, "Group 2" int, "Group 3" int, "Group 4" int)
| Group 1 | Group 2 | Group 3 | Group 4
---------+---------+---------+---------+---------
Group 1 | | 1 | | 2
Group 2 | 1 | | | 1
Group 3 | 1 | | 1 | 1
Group 4 | | | |
(4 rows)
的相同查询:
crosstab()
答案 1 :(得分:0)
...的MySQL
这是一个挑战。我将介绍所需的两个步骤:
首先,让我们构建(和调试)一个查询,列出所有调用者调用的对,其中一些是重复的。 (我们稍后会计算它们。)
SELECT ger.name AS er_name,
ged.name AS ed_name
FROM Call_details AS cd
JOIN Target_groups_map AS mer ON mer.targets = cd.caller
JOIN Target_groups_map AS med ON med.targets = cd.called
JOIN Target_groups AS ger ON ger.id = mer.target_groups
JOIN Target_groups AS ged ON ged.id = med.target_groups;
其次,让我们进行转移,计算重复次数,默认为&#39; - &#39;等等:
SELECT
er_name AS '',
IFNULL(SUM(ed_name = 'Group 1'), '-') AS 'Group 1',
IFNULL(SUM(ed_name = 'Group 2'), '-') AS 'Group 2',
IFNULL(SUM(ed_name = 'Group 3'), '-') AS 'Group 3',
IFNULL(SUM(ed_name = 'Group 4'), '-') AS 'Group 4'
FROM ( ... ) AS y
GROUP BY er_name;
对于&#39; ...&#39;从第一步开始整个查询(不要包含;
&#39;)。
SUM
可能看起来很奇怪,但这里的工作原理是:它内部的布尔表达式变为0(假)或1(真),然后SUM
有效计数。 / p>
如果组的数量不完全是4,那么您应该放弃尝试在SQL中执行此操作。当然,可以通过一个非常复杂的存储过程来构建第二个查询,但这会让我的大脑受到伤害。
每当我进行透视时,我都会用客户端语言编写代码,例如PHP。
答案 2 :(得分:0)
这个sql语句:
SELECT
tg1.name as caller,
tg2.name as called,
SUM(cd.caller IS NOT NULL AND cd.called IS NOT NULL) as cnt
FROM
Target_groups tg1 JOIN Target_groups tg2
LEFT JOIN
Target_groups_map tgm1 ON tg1.id=tgm1.target_groups
LEFT JOIN
Target_groups_map tgm2 ON tg2.id=tgm2.target_groups
LEFT JOIN
Call_details cd ON tgm1.targets=cd.caller AND tgm2.targets=cd.called
GROUP BY
tg1.id,tg2.id;
给出:
+---------+---------+------+
| caller | called | cnt |
+---------+---------+------+
| Group 1 | Group 1 | 0 |
| Group 1 | Group 2 | 1 |
| Group 1 | Group 3 | 0 |
| Group 1 | Group 4 | 2 |
| Group 2 | Group 1 | 1 |
| Group 2 | Group 2 | 0 |
| Group 2 | Group 3 | 0 |
| Group 2 | Group 4 | 1 |
| Group 3 | Group 1 | 1 |
| Group 3 | Group 2 | 0 |
| Group 3 | Group 3 | 1 |
| Group 3 | Group 4 | 1 |
| Group 4 | Group 1 | 0 |
| Group 4 | Group 2 | 0 |
| Group 4 | Group 3 | 0 |
| Group 4 | Group 4 | 0 |
+---------+---------+------+
但是如果你想要格式化你打印出来的方式你需要一个准备好的sql语句,然后做Rick James先生所说的,如果你需要它动态(不要事先知道组名)这里是一个起点:
SET @sql = NULL; SELECT GROUP_CONCAT(DISTINCT(CONCAT('"" as ',quote(name)))) INTO @sql FROM Target_groups; SET @sql = CONCAT("SELECT Target_groups.name, ", @sql, " FROM Target_groups"); PREPARE stmt FROM @sql; EXECUTE stmt;
Statement prepared
+---------+---------+---------+---------+---------+
| name | Group 1 | Group 2 | Group 3 | Group 4 |
+---------+---------+---------+---------+---------+
| Group 1 | | | | |
| Group 2 | | | | |
| Group 3 | | | | |
| Group 4 | | | | |
+---------+---------+---------+---------+---------+
ps - 这是为了帮助任何人试图解决这个+测试:
create table Targets (id int, name bigint) engine=innodb;
insert into Targets values (1,9999999991),(2,9999999992),(3,9999999993),(4,9999999994),(5,9999999995),(6,9999999996),(7,9999999997),(8,9999999998);
create table Target_groups (id int, name varchar(16)) engine=innodb;
insert into Target_groups values (1,'Group 1'),(2,'Group 2'),(3,'Group 3'),(4,'Group 4');
create table Target_groups_map (id int,targets bigint,target_groups int) engine=innodb;
insert into Target_groups_map values (1,9999999991,1),(2,9999999992,1),(3,9999999993,2),(4,9999999994,2),(5,9999999995,3),(6,9999999996,3),(6,9999999997,4),(6,9999999998,4);
create table Call_details (id int,caller bigint,called bigint) engine=innodb;
insert into Call_details values (1,9999999995,9999999996),(2,9999999992,9999999998),(3,9999999993,9999999998),(4,9999999994,9999999991),(5,9999999995,9999999998),(6,9999999996,9999999992),(6,9999999991,9999999993),(6,9999999992,9999999998);
答案 3 :(得分:-1)
我提出了一个问题:
Select A.name as caller,A.ToGroupName as called,Count(phone_number) as count
From (
Select G.id,T.phone_number,G.Name,FC.Called,TG.name as ToGroupName
From targets T
LEFT Join target_groups_map GM on GM.targets = T.phone_number
Left Join target_groups G on G.id = GM.target_groups
INNER Join call_details FC on FC.Caller = T.phone_number
INNER Join target_groups_map TGM on TGM.targets = FC.called
Inner Join target_groups TG on TG.id = TGM.target_groups
) A
Group By A.name,A.ToGroupName
Order By A.name,A.ToGroupName
提供输出:
+---------+---------+------+
| caller | called | cnt |
+---------+---------+------+
| Group 1 | Group 2 | 1 |
| Group 1 | Group 4 | 3 |
| Group 1 | Group 5 | 2 |
| Group 2 | Group 1 | 2 |
| Group 2 | Group 4 | 1 |
| Group 2 | Group 5 | 3 |
| Group 3 | Group 1 | 1 |
| Group 3 | Group 3 | 1 |
| Group 3 | Group 4 | 1 |
| Group 3 | Group 5 | 1 |
| Group 4 | Group 2 | 1 |
| Group 5 | Group 2 | 2 |
+---------+---------+------+
将其转换为矩阵格式