Sql 在多对多表上将行转换为列
所以我有三张桌子: 学生:Sql 在多对多表上将行转换为列,sql,sql-server,tsql,pivot,left-join,Sql,Sql Server,Tsql,Pivot,Left Join,所以我有三张桌子: 学生: StuID ------ 1 2 斯图肯: StuConId StuID ConID StuConType Priority ---------------------------------------------- 1 1 1 Parent 1 2 1 2 Guardian 2 3 2 3 Parent 1
StuID
------
1
2
斯图肯:
StuConId StuID ConID StuConType Priority
----------------------------------------------
1 1 1 Parent 1
2 1 2 Guardian 2
3 2 3 Parent 1
联系人:
ConID ConName ConPhn
----------------------
1 John 5555555
2 Sally 4444444
3 Dana 3333333
我试图得到如下结果:
StuID ConID1 StuConType1 ConName1 ConPhone1 ConID2 StuConType2 ConName2 ConPhone2
----------------------------------------------------------------------------------------
1 1 Parent John 5555555 2 Guardian Sally 4444444
2 3 Parent Dana 3333333 Null Null Null Null
到目前为止,我唯一能想到的方法是做大量的左连接(一些学生最多有10个联系人,因此stucon有10个左连接,联系人有10个)
我很确定这里有一个可以应用的轴心,但我就是不知道怎么做。这里有一种动态实现的方法:
DECLARE @selects VARCHAR(MAX) = '', @SQL VARCHAR(MAX) = '';
SELECT @selects += '
, MAX(CASE WHEN SC.[Priority] = ' + CAST([Priority] AS VARCHAR(255)) + ' THEN C.ConID END) [ConID' + CAST([Priority] AS VARCHAR(255)) + ']
, MAX(CASE WHEN SC.[Priority] = ' + CAST([Priority] AS VARCHAR(255)) + ' THEN SC.StuConType END) [StuConType' + CAST([Priority] AS VARCHAR(255)) + ']
, MAX(CASE WHEN SC.[Priority] = ' + CAST([Priority] AS VARCHAR(255)) + ' THEN C.ConName END) [ConName' + CAST([Priority] AS VARCHAR(255)) + ']
, MAX(CASE WHEN SC.[Priority] = ' + CAST([Priority] AS VARCHAR(255)) + ' THEN C.ConPhn END) [ConPhone' + CAST([Priority] AS VARCHAR(255)) + ']'
FROM StuCon
GROUP BY [Priority]
ORDER BY [Priority];
SET @SQL = 'SELECT StuID' + @selects + ' FROM StuCon SC LEFT JOIN Contacts C ON C.ConID = SC.ConID GROUP BY StuID;';
EXEC(@SQL);
注意:它可能应该是联系人上的正常
连接
,而不是左连接
,但这里是左连接,以防表之间存在一些不一致。Students
表没有加入,因为它不是必需的。这里有一种动态加入的方法:
DECLARE @selects VARCHAR(MAX) = '', @SQL VARCHAR(MAX) = '';
SELECT @selects += '
, MAX(CASE WHEN SC.[Priority] = ' + CAST([Priority] AS VARCHAR(255)) + ' THEN C.ConID END) [ConID' + CAST([Priority] AS VARCHAR(255)) + ']
, MAX(CASE WHEN SC.[Priority] = ' + CAST([Priority] AS VARCHAR(255)) + ' THEN SC.StuConType END) [StuConType' + CAST([Priority] AS VARCHAR(255)) + ']
, MAX(CASE WHEN SC.[Priority] = ' + CAST([Priority] AS VARCHAR(255)) + ' THEN C.ConName END) [ConName' + CAST([Priority] AS VARCHAR(255)) + ']
, MAX(CASE WHEN SC.[Priority] = ' + CAST([Priority] AS VARCHAR(255)) + ' THEN C.ConPhn END) [ConPhone' + CAST([Priority] AS VARCHAR(255)) + ']'
FROM StuCon
GROUP BY [Priority]
ORDER BY [Priority];
SET @SQL = 'SELECT StuID' + @selects + ' FROM StuCon SC LEFT JOIN Contacts C ON C.ConID = SC.ConID GROUP BY StuID;';
EXEC(@SQL);
注意:它可能应该是联系人上的正常
连接
,而不是左连接
,但这里是左连接,以防表之间存在一些不一致。Students
表没有被加入,因为它不是必需的。google Dynamic Pivot…………我认为这里不需要Pivot。第一个联系人集上的一个连接优先级为1,第二个联系人集上的一个左连接优先级为2。google Dynamic Pivot…………我认为这里不需要Pivot。第一个联系人集中的一个连接优先级为1,第二个联系人集中的一个左连接优先级为2。此处不需要动态sql。@shawnt00您不需要动态sql,但考虑到每个学生最多可以有十个联系人(假设这不是限制),这比为十个联系人写几行要容易(假设这是最大值)…我忽略了提到10个联系人。虽然这种方法有一定的经济性,但动态sql有很多缺点,因为结果中的列数突然变化。@shawnt00结果中的列数将根据联系人的最大数量而变化。如果10是绝对限值,您不想使用d动态SQL出于这样或那样的原因,那么是的,您可以在不使用动态SQL的情况下执行此操作。如果最大数量发生变化,则可能会丢失数据。但是,是的,动态SQL可能会出现问题,这取决于您输出数据的方式。如果出于某种原因需要使用静态方法,OP可以始终PRINT@SQL
。此处不需要动态sql。@shawnt00您不需要动态sql,但考虑到每个学生最多可以有十个联系人(假设这不是限制),这比为十个联系人写几行要容易(假设这是最大值)…我忽略了提到10个联系人。虽然这种方法有一定的经济性,但动态sql有很多缺点,因为结果中的列数突然变化。@shawnt00结果中的列数将根据联系人的最大数量而变化。如果10是绝对限值,您不想使用d动态SQL出于这样或那样的原因,那么是的,您可以在不使用动态SQL的情况下执行此操作。如果最大数量发生变化,则可能会丢失数据。但是,是的,动态SQL可能会出现问题,这取决于您输出数据的方式。如果出于某种原因需要使用静态方法,OP可以始终PRINT@SQL
.