SQL aggregation query, grouping by entries in junction table

耗尽温柔 提交于 2019-12-13 01:07:49

问题


I have TableA in a many-to-many relationship with TableC via TableB. That is,

TableA       TableB           TableC
id | val     fkeyA | fkeyC    id | data

I wish the do select sum(val) on TableA, grouping by the relationship(s) to TableC. Every entry in TableA has at least one relationship with TableC. For example,

TableA
1 | 25
2 | 30
3 | 50

TableB
1 | 1
1 | 2
2 | 1
2 | 2
2 | 3
3 | 1
3 | 2

should output

75
30

since rows 1 and 3 in Table have the same relationships to TableC, but row 2 in TableA has a different relationship to TableC.

How can I write a SQL query for this?


回答1:


SELECT    
   sum(tableA.val) as sumVal,    
   tableC.data  
FROM    
   tableA 
     inner join tableB ON tableA.id = tableB.fkeyA 
     INNER JOIN tableC ON tableB.fkeyC = tableC.id  
GROUP by tableC.data

edit Ah ha - I now see what you're getting at. Let me try again:

SELECT
   sum(val) as sumVal,
   tableCGroup
FROM
(

SELECT 
   tableA.val,
   (
      SELECT cast(tableB.fkeyC as varchar) + ',' 
      FROM tableB WHERE tableB.fKeyA = tableA.id
      ORDER BY tableB.fkeyC
      FOR XML PATH('') 
   ) as tableCGroup
FROM
   tableA


) tmp
GROUP BY
    tableCGroup



回答2:


Hm, in MySQL it could be written like this:

SELECT
    SUM(val) AS sumVal
FROM
    ( SELECT
          fkeyA
        , GROUP_CONCAT(fkeyC ORDER BY fkeyC) AS grpC
      FROM 
          TableB
      GROUP BY
          fkeyA
    ) AS g
  JOIN
    TableA a
      ON a.id = g.fkeyA
GROUP BY 
    grpC



回答3:


SELECT sum(a.val) 
FROM  tablea a
INNER JOIN tableb b ON (b.fKeyA = a.id)
GROUP BY b.fKeyC



回答4:


It seems that is it needed to create a key_list in orther to allow group by:

75 -> key list = "1 2"
30 -> key list = "1 2 3"

Because GROUP_CONCAT don't exists in T-SQL:

WITH CTE ( Id, key_list )
          AS ( SELECT TableA.id, CAST( '' AS VARCHAR(8000) )
                 FROM TableA 
                GROUP BY TableA.id
                UNION ALL
               SELECT TableA.id, CAST( key_list + ' ' + str(TableB.id) AS VARCHAR(8000) )
                 FROM CTE c
                INNER JOIN TableA A
                   ON c.Id = A.id
                INNER join TableB B
                   ON B.Id = A.id
                WHERE A.id > c.id      --avoid infinite loop
              )
Select
   sum( val )
from 
   TableA inner join
   CTE on (tableA.id = CTE.id)
group by
   CTE.key_list


来源:https://stackoverflow.com/questions/8216079/sql-aggregation-query-grouping-by-entries-in-junction-table

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!