2

ユーザー用のテーブルがあります:

USERS:
ID   |   NAME  | 
----------------
1    |   JOHN  |
2    |   STEVE |

コンピュータ用のテーブル:

COMPUTERS:
ID   |   USER_ID |
------------------
13   |     1     |
14   |     1     |

プロセッサのテーブル:

PROCESSORS:
ID   |   NAME             |
---------------------------
27   |   PROCESSOR TYPE 1 |
28   |   PROCESSOR TYPE 2 |

およびハードドライブの表:

HARDDRIVES:
ID   |   NAME              |
---------------------------|
35   |   HARDDRIVE TYPE 25 |
36   |   HARDDRIVE TYPE 90 |

各コンピューターは、さまざまな属性テーブル (プロセッサー、ハードドライブなど) からの多くの属性を持つことができるため、属性をコンピューターにリンクするために、次のような交差テーブルを作成します。

COMPUTER_PROCESSORS:
C_ID |  P_ID  |
--------------|
13   |   27   |
13   |   28   |
14   |   27   |

COMPUTER_HARDDRIVES:
C_ID |  H_ID  |
--------------|
13   |   35   |

したがって、ID 1 のユーザー JOHN は、コンピューター 13 と 14 を所有しています。コンピューター 13 にはプロセッサー 27 と 28 があり、コンピューター 13 にはハードドライブ 35 があります。

ユーザーのIDを指定して、そのユーザーのコンピューターのリストを各コンピューターの属性とともに取得したいと思います。

ある程度の結果が得られるクエリを見つけました。

SELECT computers.id, processors.id AS p_id, processors.name AS p_name, harddrives.id AS h_id, harddrives.name AS h_name,
FROM computers

JOIN computer_processors ON (computer_processors.c_id = computers.id) 
JOIN processors ON (processors.id = computer_processors.p_id)

JOIN computer_harddrives ON (computer_harddrives.c_id = computers.id) 
JOIN harddrives ON (harddrives.id = computer_harddrives.h_id)

WHERE computers.user_id = 1

結果:

ID   | P_ID | P_NAME           | H_ID | H_NAME            |
-----------------------------------------------------------
13   |  27  | PROCESSOR TYPE 1 |  35  | HARDDRIVE TYPE 25 |
13   |  28  | PROCESSOR TYPE 2 |  35  | HARDDRIVE TYPE 25 |

しかし、これにはいくつかの問題があります...

  1. コンピューター 14 は、ハードドライブがないため表示されません。 何らかの属性が存在しない場合でも、すべてのコンピューターが確実に表示されるように OUTER JOIN を作成できますか?

  2. コンピューター 13 が 2 回表示され、両方のハードドライブ リストセットが同じです。より多くの属性がコンピューターに追加されると (RAM の 3 ブロックなど)、そのコンピューターに対して返される行の数がかなり大きくなるため、アプリケーション コードで結果を並べ替える必要が生じます。返された 2 つの行をグループ化するクエリを作成できますか? または、返されるすべての値が一意になるように、2 行目の h_name 列に NULL を返すクエリですか?

編集:私が返したいのは次のようなものです:

ID   | P_ID | P_NAME           | H_ID | H_NAME            |
-----------------------------------------------------------
13   |  27  | PROCESSOR TYPE 1 |  35  | HARDDRIVE TYPE 25 |
13   |  28  | PROCESSOR TYPE 2 |  35  | NULL              |
14   |  27  | PROCESSOR TYPE 1 | NULL | NULL              |

または、このような配列に簡単に変換できる結果

[13] =>
    [P_NAME] =>
         [0] => PROCESSOR TYPE 1
         [1] => PROCESSOR TYPE 2
    [H_NAME] =>
         [0] => HARDDRIVE TYPE 25


[14] =>
    [P_NAME] =>
         [0] => PROCESSOR TYPE 1
4

4 に答える 4

4

LEFT JOINの代わりに使用しINNER JOINます。2 つの結合は互いに異なります。(現在使用しているINNER JOIN)は、テーブルの両側に少なくとも 1 つの一致があるレコードのみを返します。そして、table に一致するものがないため、そうすべきではありません。一方、テーブルの反対側で一致しないかどうかにかかわらず、左側のテーブルのすべてのレコードを返します。computer 14COMPUTER_HARDDRIVESLEFT JOIN

SELECT  a.ID AS UserID,
        a.Name as UserName,
        b.ID as ComputerID,
        d.ID as ProcessorID,
        d.Name as ProcessorName,
        f.ID as HardDriveID,
        f.name as HardDriveName
FROM    users a
        INNER JOIN computers b
            ON a.ID = b.user_ID
        LEFT JOIN computer_processors c
            ON b.ID = c.C_ID
        LEFT JOIN PROCESSORS d
            ON c.p_ID = d.ID
        LEFT JOIN COMPUTER_HARDDRIVES e
            ON b.ID = e.c_ID
        LEFT JOIN HARDDRIVE f
            ON e.h_ID = f.ID
WHERE   a.ID = 1

行をまとめてグループ化したいので、GROUP_CONCAT()関数を利用できます。基本的に、それは列の値をコンマ区切りの値に結合することです

SELECT  a.ID AS UserID,
        a.Name as UserName,
        b.ID as ComputerID,
        GROUP_CONCAT(DISTINCT d.ID) as ProcessorID,
        GROUP_CONCAT(DISTINCT d.Name) as ProcessorName,
        GROUP_CONCAT(DISTINCT f.ID) as HardDriveID,
        GROUP_CONCAT(DISTINCT f.name) as HardDriveName
FROM    users a
        INNER JOIN computers b
            ON a.ID = b.user_ID
        LEFT JOIN computer_processors c
            ON b.ID = c.C_ID
        LEFT JOIN PROCESSORS d
            ON c.p_ID = d.ID
        LEFT JOIN COMPUTER_HARDDRIVES e
            ON b.ID = e.c_ID
        LEFT JOIN HARDDRIVE f
            ON e.h_ID = f.ID
WHERE   a.ID = 1
GROUP BY UserID, UserName, ComputerID
于 2012-10-29T10:14:20.797 に答える
3

試す:

SELECT computers.id, 
       group_concat(distinct processors.id) AS p_ids, 
       group_concat(distinct processors.name) AS p_names, 
       group_concat(distinct harddrives.id) AS h_ids, 
       group_concat(distinct harddrives.name) AS h_names
FROM computers
JOIN computer_processors ON (computer_processors.c_id = computers.id) 
JOIN processors ON (processors.id = computer_processors.p_id)
LEFT JOIN computer_harddrives ON (computer_harddrives.c_id = computers.id) 
LEFT JOIN harddrives ON (harddrives.id = computer_harddrives.h_id)
WHERE computers.user_id = 1
group by computers.id
于 2012-10-29T10:11:47.327 に答える
1
SELECT computers.id, processors.id AS p_id, processors.name AS p_name, harddrives.id AS h_id, harddrives.name AS h_name
FROM computers

LEFT JOIN computer_processors ON (computer_processors.c_id = computers.id) 
LEFT JOIN processors ON (processors.id = computer_processors.p_id)

LEFT JOIN computer_harddrives ON (computer_harddrives.c_id = computers.id) 
LEFT JOIN harddrives ON (harddrives.id = computer_harddrives.h_id)

WHERE computers.user_id = 1
于 2012-10-29T10:08:01.357 に答える
0
select u.ID user_id,
       u.name user_name
       p.id,
       p.name,
       h.id,
       h.name
from USERS u join COMPUTERS c
on u.id=c.USER_ID
join PROCESSORS p
on c.id=p.id
join HARDDRIVES h
on c.id=h.id
where u.id=1
于 2012-10-29T10:05:38.553 に答える