在SELECT期间使用JOIN操作替换子记录列

时间:2015-09-02 09:50:10

标签: sql sql-server join view replace

我试图通过将两个表连接在一起来创建视图,这绝非困难。但是有一个但是。

我基本上有两张桌子。其中一个存储项目和标签之间的关联,另一个存储父母 - 儿童形式的标签(8个父母,每个孩子有4-6个孩子)。

请允许我说明从我的项目关联表开始:

AssociationId | ItemId | TagId
------------------------------
1             | 2      | 1
2             | 10     | 2
3             | 3      | 1
4             | 5      | 7
...

我的标签表:

TagId | ParentId | Name
------------------------------
1     | NULL     | abc sds
2     | 1        | sjdksd as
3     | 1        | djfsd dfs d
4     | NULL     | ujkjsd as
...

正如您所见,通过使用ParentId IS NULL装饰查询可以找到每个父级。

SELECT ITA.AssociationId, ITA.ItemId, ITA.TagId, T.Name as TagName
FROM Item_Tag_Association AS ITA
INNER JOIN Tags AS T
ON T.TagId = ITA.TagId
WHERE T.ParentId IS NULL

如果我要TagIdParentId IS NULL加入两个表格,我会找到所有带有父标记的项目。

如果我要TagIdParentId IS NOT NULL加入两个表格,我会找到所有带有子标记的项目。

但我真正想要的是一个项目和标签列表,其中子标签被父标签取代。

使用上面的例子,结果看起来像这样:

AssociationId | ItemId | TagId | TagName
----------------------------------------
1             | 2      | 1     | abc sds
2             | 10     | 1     | abc sds
3             | 3      | 1     | abc sds
4             | 5      | 7     | ysdasjdhas
...

至于我想要这样做的原因是,我可以计算特定父标记(或该父项的子项)与项目关联的次数。正如你猜到的那样,现在每个孩子都应该为其父母做出贡献。

SELECT DISTINCT ItemId, TagId, TagName, COUNT(ItemId) OVER (PARTITION BY TagId) AS Count
FROM vw_My_View
ORDER BY Count DESC

我正在使用SQL Server 2008 R2。欢迎提出所有建设性意见。

1 个答案:

答案 0 :(得分:1)

只要您的父/子层次结构中只有一个级别,您就可以从标签到其自身进行额外的左连接,如果它存在,则可以找到父级:

SELECT ita.AssociationId, ita.ItemId, ISNULL(parent.TagId, t.TagId), ISNULL(parent.Name, t.Name) AS TagName
FROM Item_Tags_Association ita
  JOIN Tags t ON ita.TagId = t.TagId
  LEFT JOIN Tags parent ON t.ParentId = parent.TagId

第一个(内部)联接可以加入子标记或父标记。如果关联的标记具有父标记,则左连接将包含父标记。 如果不是null,ISNULL将确保使用第二个(左)连接的值,否则使用第一个连接中的值。

如果您不想与ISNULL(或COALESCE)打交道,可以使用UNIONCTE这样的内容:

WITH ParentTags AS (SELECT * FROM Tags WHERE ParentId IS NULL)
SELECT ita.AssociationId, ita.ItemId, t.TagId, t.Name AS TagName
FROM ParentTags t
  JOIN Item_Tags_Association ita ON ita.TagId = t.TagId
UNION ALL 
SELECT ita.AssociationId, ita.ItemId, t.TagId, t.Name AS TagName
FROM ParentTags t
  JOIN Tags child ON t.TagId = child.ParentId
  JOIN Item_Tags_Association ita ON ita.TagId = child.TagId