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

时间:2012-05-07 08:59:41

标签: 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

这是表格结构

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

4 个答案:

答案 0 :(得分:7)

“每个父行只从子表中获取一行并包含子字段”

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

SELECT pID, Min(cID) AS MinOfcID
FROM child
GROUP BY pID;

再次将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;

最后,要包含lastname值,请将parent表加入qryChild

答案 1 :(得分:3)

您没有说明您的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

您定义为“第一”行的哪些行取决于您。除非您对行进行排序,否则不存在诸如“第一”行 - 这就是部分order by cid在分区子句中的作用。因此,如果你想要一些不同的东西作为“第一”行,你需要改变它。

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

答案 2 :(得分:0)

你必须更换

SELECT cID, pID, phone, company, title FROM child

每个pid只返回一行。正确的选择取决于您的要求。简单是group by

SELECT min(cID), pID, min(phone), min(company), min(title) FROM child group by cID

但是不同的列将来自不同的行,所以你可能想要“第一行”如何实现,这取决于你正在使用的RDBMS,所以请将这些信息添加到你的问题中。

答案 3 :(得分:0)

SELECT cID ChildID, 
       pID ParentID, 
       phone, 
       company, 
       title, 
       (SELECT lastname FROM parent WHERE id = ParentID) as LastName
FROM child
GROUP BY ParentID