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。计算机 14 具有处理器 27,但没有硬盘驱动器。

给定用户的 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 出现两次,两者的硬盘列表相同。当向计算机添加更多属性时(例如 3 块 ram),为该计算机返回的行数变得非常大,这使得它必须在应用程序代码中对结果进行排序。我可以以某种方式进行查询,将返回的两个行组合在一起吗?还是在第二行的 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. 这两个连接彼此不同。(您当前正在使用INNER JOIN的)仅返回在表的任一侧都至少有一个匹配项的记录。这就是为什么不应该,因为它在 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 回答