2016-09-07 4 views
1

4テーブルから生成されるMySQLまたはpostgresでクエリを作成したいと思います。行列テーブルのPostgresクエリ

次の表を参照してください。

以下に定義されている行列テーブルの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

にそれを変換し、あなたが 'JOINs'との助けが必要ですか?または「ピボット」を使用していますか?または両方? –

+0

私は必要な出力だけが必要です。結合またはピボットのいずれかを使用できます。 –

+0

両方必要です。私はあなたが1つの部分をすることができるかどうかを調べていました。 –

答えて

3

あなたはピボットテーブルを生成するために拡張tablefuncを必要とする:crosstab()

create extension if not exists tablefunc; 

クエリを:

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) 

の代わりにstring_agg()という集合関数を使用した同じクエリ:

select caller_name as " ", string_agg(coalesce(count::text, '-'), ', ') matrix 
from (
    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 
    ) sub 
group by 1 
order by 1; 

     | matrix 
---------+------------ 
Group 1 | -, 1, -, 2 
Group 2 | 1, -, -, 1 
Group 3 | 1, -, 1, 1 
Group 4 | -, -, -, - 
(4 rows) 
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; 

第二に、のは、ピボットをやらせる、DUPをカウントし、デフォルトにする ' - ' など: '...' 置くために

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; 

を最初のステップからのクエリ全体(; 'は含まれません)。

SUMが奇妙に見えるかもしれませんが、その仕組みは次のとおりです。ブール式が0(偽)または1(真)に変わると、SUMが有効にカウントされます。

グループの数が正確に4でない場合は、SQLでこれを行うことを中止する必要があります。確かに、それは2番目のクエリを構築するために実際に複雑なストアドプロシージャで行うことができますが、それは私の脳を傷つける。

私はピボットするたびに、クライアント言語(PHPなど)でコードを記述します。

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文を必要とし、その後、何氏リックをやるプリントアウトしている正確にどのようにフォーマットしたい場合は、ジェームズ氏は、ダイナミック(グループ名はあらかじめわかっていない)が必要な場合は、ここで始点とします:

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 - これは、この+テストを解決しようとする人を支援することです:Postgresので

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); 
-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 | 
+---------+---------+------+ 

は行列形式

関連する問題