一对多查询选择每个父母的所有父母和单个顶级孩子

Pio*_*trK 20 sql t-sql sql-server greatest-n-per-group

有两个SQL表:

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

Childs
+--+------+-------+
|id|parent|feature|
+--+------+-------+
| 1|   1  |  123  |
| 2|   1  |   35  |
| 3|   2  |   15  |
+--+------+-------+
Run Code Online (Sandbox Code Playgroud)

我想从Parents表的每一行中选择单个查询,并从Childs表中选择与"parent" - "id"值和最大"feature"列值相关的每一行.在此示例中,结果应为:

+----+------+----+--------+---------+
|p.id|p.text|c.id|c.parent|c.feature|
+----+------+----+--------+---------+
|  1 | Blah |  1 |    1   |    123  |
|  2 | Blah2|  3 |    2   |    15   |
|  3 | Blah3|null|   null |   null  |
+----+------+----+--------+---------+
Run Code Online (Sandbox Code Playgroud)

其中p =父表和c =子表

我尝试LEFT OUTER JOIN和GROUP BY,但MSSQL Express告诉我,使用GROUP BY的查询需要在每个非Groupped字段上使用Aggregate函数.而且我不想将它们全部分组,而是选择顶行(使用自定义排序).

我完全没有想法......

man*_*nji 17

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
Run Code Online (Sandbox Code Playgroud)

  • 当然,工作代码是最重要的,但对其工作方式的一些解释将是很好的. (3认同)

OMG*_*ies 9

使用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
Run Code Online (Sandbox Code Playgroud)

非CTE等效物:

   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
Run Code Online (Sandbox Code Playgroud)

您的问题缺乏处理断路器的详细信息(当2+ CHILD.id值具有相同的特征值时).Agent_9191的答案使用了TOP 1,但这将是第一个返回的,而不一定是你想要的.

  • 我认为按(c.id,c.parent)分组就像返回原始表(Childs),因为父级不能拥有具有2个功能的同一个子级。 (2认同)

Age*_*191 5

这应该有效:

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
Run Code Online (Sandbox Code Playgroud)