one-to-many query selecting all parents and single top child for each parent

后端 未结 5 1776
别那么骄傲
别那么骄傲 2020-12-24 07:31

There are two SQL tables:

Parents:
+--+---------+
|id|   text  |
+--+---------+
| 1|  Blah   |
| 2|  Blah2  |
| 3|  Blah3  |
+--+---------+

Childs
+--+-----         


        
相关标签:
5条回答
  • 2020-12-24 08:06

    This should work:

    SELECT p.id, p.text, c.id, c.parent,c.feature
    FROM parent p
     LEFT OUTER JOIN (SELECT TOP 1 child.id,
                                   child.parent,
                                   MAX(child.feature)
                      FROM child
                      WHERE child.parent = p.id
                      GROUP BY child.id, child.parent
                      ) c ON p.id = c.parent
    
    0 讨论(0)
  • 2020-12-24 08:11

    If you need to join different from a MAX column and any columns described in a group by closure of a nested select, you can use an APPLY function. It is a simplest solution. You also can use WITH operator. But that look harder.

    SELECT p.id, p.text, CHILD_ROW.ANY_COLLUMN
    FROM parent p
    OUTER APPLY (SELECT TOP 1 child.ANY_COLLUMN
                      FROM child
                      WHERE child.parent = p.id
                      ORDER BY child.feature DESC 
                      ) CHILD_ROW
    
    0 讨论(0)
  • 2020-12-24 08:15

    manji's query does not handle tie-breakers for max feature. Here is my method, which I've tested:

    ;WITH WithClause AS (SELECT p.id, p.text, 
            (SELECT TOP 1 c.id from childs c 
                where c.parent = p.id order by c.feature desc) 
            AS BestChildID
        FROM Parents p) 
    SELECT WithClause.id, WithClause.text, c.id, c.parent, c.feature
    FROM WithClause 
    LEFT JOIN childs c on WithClause.BestChildID = c.id
    
    0 讨论(0)
  • 2020-12-24 08:22

    Using CTE (SQL Server 2005+):

    WITH max_feature AS (
       SELECT c.id,
              c.parent,
              MAX(c.feature) 'feature'
         FROM CHILD c
     GROUP BY c.id, c.parent)
       SELECT p.id,
              p.text,
              mf.id,
              mf.parent,
              mf.feature
         FROM PARENT p
    LEFT JOIN max_feature mf ON mf.parent = p.id
    

    Non CTE equivalent:

       SELECT p.id,
              p.text,
              mf.id,
              mf.parent,
              mf.feature
         FROM PARENT p
    LEFT JOIN (SELECT c.id,
                      c.parent,
                      MAX(c.feature) 'feature'
                 FROM CHILD c
             GROUP BY c.id, c.parent) mf ON mf.parent = p.id
    

    Your question lacks details for handling tie breakers (when 2+ CHILD.id values have the same feature value). Agent_9191's answer uses TOP 1, but that will take the first that is returned & not necessarily the one you want.

    0 讨论(0)
  • 2020-12-24 08:25
    select p.id, p.text, c.id, c.parent, c.feature
    from Parents p
    left join (select c1.id, c1.parent, c1.feature
                 from Childs c1
                 join (select p1.id, max(c2.feature) maxFeature
                         from Parents p1
                    left join Childs c2 on p1.id = c2.parent
                group by p1.id) cf on c1.parent = cf.id 
                                  and c1.feature = cf.maxFeature) c
    on p.id = c.parent
    
    0 讨论(0)
提交回复
热议问题