从子表中为父表中的每一行选择单行

meY*_*not 4 sql ms-access

我试图从包含子字段的每个父行的子表中只获取一行,我一直尝试使用GRUOP BY但没有成功:(这是我的初始SELECT

SELECT pID, lastname 
 FROM parent 
  LEFT JOIN 
   (SELECT cID, pID, phone, company, title FROM child) as child 
   ON parent.pID = child.pID
Run Code Online (Sandbox Code Playgroud)

这是表格结构

CREATE TABLE parent (
    pID Counter(1,1) PRIMARY KEY,
    firstname VarChar(24) DEFAULT '',
    lastname VarChar(20) DEFAULT ''
);

CREATE TABLE child (
    cID Counter(1,1) PRIMARY KEY,
    pID int DEFAULT '0',
    phone VarChar(16) DEFAULT '',
    company VarChar(24) DEFAULT '',
    title VarChar(24) DEFAULT '',
    address TEXT
);
Run Code Online (Sandbox Code Playgroud)

Han*_*sUp 8

"对于包含子字段的每个父行,只从子表中获取一行"

听起来这个child表可以有相同pID值的多行.而且child每个只需要一行pID.

SELECT pID, Min(cID) AS MinOfcID
FROM child
GROUP BY pID;
Run Code Online (Sandbox Code Playgroud)

再次将该GROUP BY查询加入child表中,以检索每个目标值的其他列cID.将此查询另存为qryChild.

SELECT
    c.pID,
    c.cID,
    c.phone,
    c.company,
    c.title,
    c.address
FROM
    (
        SELECT pID, Min(cID) AS MinOfcID
        FROM child
        GROUP BY pID
    ) AS map
    INNER JOIN child AS c
    ON c.cID = map.MinOfcID;
Run Code Online (Sandbox Code Playgroud)

最后,要包含lastname值,请将parent表连接到qryChild.


a_h*_*ame 5

您没有说明您的 DBMS,所以这是一个标准的 ANSI 解决方案:

SELECT pID, lastname 
FROM parent 
  LEFT JOIN (
         SELECT pID, 
                row_number() over (partition by pid order by cid) as rn
         FROM child
         ) as child 
         ON parent.pID = child.pID and child.rn = 1
Run Code Online (Sandbox Code Playgroud)

您将哪些行定义为“第一”行取决于您。除非您对行进行排序,否则没有“第一”行之类的 ​​- 这就是该部分order by cid在分区子句中所做的。因此,如果您想要与“第一”行不同的内容,则需要更改它。

顺便说一句:如果您不使用它们,则无需从子表中选择所有列。