SQL Join / Pivot / Unpivot = 疯狂

6

所以,我已经进行了相当多的搜索和试验,但还是找不到解决方案。也许我的情况很独特——或者更可能的是我根本不知道自己在做什么。不过我比开始时更接近成功了,这让人振奋。好了,现在我们来看看问题吧——任何帮助都将不胜感激。

我需要连接两个查找表,它们看起来像这样(由于没有足够的声望点数来发布图片,因此以下是我的虚拟表):

Social Network Member [table]
member_id     social_network_id     connection_id_string
16972         1                     www.linkedin.com/somename
16972         2                     www.twitter.com/somename
16972         3                     www.facebook.com/somename
180301        1                     www.linkedin.com/anothername

Social Network [table]
social_network_id     name     calling_string
1                     Linkedin www.linkedin.com
2                     Twitter  www.twitter.com
3                     Facebook www.facebook.com

我希望你能帮我翻译这段内容。它与IT技术有关,我尝试过许多方法,包括数据透视和反透视、交叉应用等,但似乎无法得到这个结果:

member_id   linkedin                     facebook                     twitter
16972       www.linkedin.com/somename    www.facebook.com/somename    www.twitter.com/somename

我可以处理这个,我在join之后不需要social_network_id或calling_string。这是我的查询,但它还没有完全解决问题。

SELECT member_id, [facebook],[linkedin],[myspace],[twitter]
FROM (
SELECT member_id,name,social_network_id,calling_string,connection_id_string
FROM social_network_member INNER JOIN
social_network ON social_network_member.social_network_id = social_network.social_network_id
CROSS APPLY (VALUES ('NAME',name),
('CONNECTION STRING', connection_id_string),
('CALLING STRING',calling_string))
Unpivoted(club_id,member_id)) as Sourcetable
Pivot (MAX(connection_id_string) For name in([facebook],[linkedin],[myspace],[twitter])) AS PVT

据我所知,交叉应用程序实际上并没有起到任何作用。我在语法方面有些猜测...你能告诉我吗?

这就是我得到的结果(从我搜索中看到的典型情况):

member_id     facebook                  linkedin                    myspace     twitter
16972         NULL                      www.linkedin.com/somename   NULL        NULL
16972         www.facebook.com/somename NULL                        NULL        NULL
...
...

我想知道我是否能实现我的愿望?有没有指导如何达到目标的提示?我的查询是不是出了问题?

谢谢各位。

我之前忘了提到,我正在使用 SQL Server 2012 - SSMS。

已解决 我使用了下面Bluefeet提供的答案,它运行得很好。同时感谢Cha花时间帮忙。


只需要这三个网络,还是查询应该处理任意数量的网络,只要它们在“社交网络”表中?如果只有三个,您应该能够使用三个“CASE WHEN”结构来完成。 - PM 77-1
你使用哪个关系型数据库管理系统? - Dale M
Cross Apply 只适用于 MSSQL。@apoji187 的第一篇帖子很棒,提供了表创建和选择语句的详细描述...很明显你已经尝试自己解决了问题。在以后的工作中,请记得在标签中添加你正在使用的数据库,这样人们就知道你使用的是哪种 SQL...跨应用/交叉连接语法在不同的数据库中非常独特。 - Twelfth
@Twelfth - 感谢你的赞美之词。我有点预料到会被喷:)。我正在使用SSMS - SQL Server 2012。 - apoji187
2个回答

3

您当前的查询非常接近目标。如果您上面的表格结构是正确的,那么似乎不需要使用 CROSS APPLY,因为您没有任何需要被旋转的内容。

如果您去掉 CROSS APPLY,则可以轻松使用 PIVOT 获取结果:

SELECT member_id, [facebook],[linkedin],[myspace],[twitter]
FROM
(
  SELECT m.member_id,
    n.name,
    m.connection_id_string
  FROM social_network_member m
  INNER JOIN social_network n
    ON m.social_network_id = n.social_network_id
) d
pivot
(
  max(connection_id_string)
  for name in ([facebook],[linkedin],[myspace],[twitter])
) piv;

请查看带演示的SQL Fiddle

如果您有未知数量的值,可以使用动态SQL:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(name) 
                    from social_network
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT member_id, ' + @cols + ' 
            from 
            (
              SELECT m.member_id,
                n.name,
                m.connection_id_string
              FROM social_network_member m
              INNER JOIN social_network n
                ON m.social_network_id = n.social_network_id
            ) x
            pivot 
            (
                max(connection_id_string)
                for name in (' + @cols + ')
            ) p '

execute sp_executesql @query;

请查看带有演示的SQL Fiddle

1
首先感谢您抽出时间来审查并创建这个代码片段。同时也感谢您提供了动态示例。我希望这对其他人有所帮助。我为过度思考查询问题感到有些傻,但绝望是一件有趣的事情。再次感谢。 - apoji187

1

我认为这是一个非常简单的PIVOT案例。你根本不需要用CROSS APPLY/JOIN等复杂的方法来使它变得更加复杂。像这样简单的查询就可以:

SELECT member_id, [facebook],[linkedin],[myspace],[twitter]
FROM (
SELECT member_id,name,connection_id_string
FROM social_network_member snm INNER JOIN
social_network sn ON snm.social_network_id = sn.social_network_id
) as Sourcetable
Pivot (MAX(connection_id_string) For [name] in([facebook],[linkedin],[myspace],[twitter])) AS PVT

提示:在PIVOT的SourceTable中不要包含不必要的列。 SQL Fiddle

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接