SQL-在一个表中联合所有用户
表:受欢迎 UserName FriendName -------- ---------- John Sarah Philip Ursula John Marry John Jeremy Philip Brock Khan Lemy 我要带查询的列表 John Philip Khan -------- ---------- -------- Sarah Ursula Lemy Marry Brock -NULL- Jeremy -NULL- -NULL- 我有100多个用户名。。。帮助我列出使用SQL查询MSSQL时的用例SQL-在一个表中联合所有用户,sql,sql-server,unpivot,Sql,Sql Server,Unpivot,表:受欢迎 UserName FriendName -------- ---------- John Sarah Philip Ursula John Marry John Jeremy Philip Brock Khan Lemy 我要带查询的列表 John Philip Khan -------- ---------- -------- Sarah Ursula L
select max(case when UserName='John' then fieldname end) as john,
max(case when UserName='Philip' then fieldname end) as Philip,
max(case when UserName='Khan' then fieldname end) as Khan
from table_name
编辑:您需要行号:
我想你可以用枢轴
这就是代码:
if OBJECT_ID('userName') is not null drop table userName;
create table userName (fiiduserName int identity(1,1), fcName varchar(20),
fcFrienlyName varchar(20));
insert into userName(fcName, fcFrienlyName)values ('John', 'Sarah');
insert into userName(fcName, fcFrienlyName)values ('Philip', 'Ursula');
insert into userName(fcName, fcFrienlyName)values ('John', 'Marry');
insert into userName(fcName, fcFrienlyName)values ('John', 'Jeremy');
insert into userName(fcName, fcFrienlyName)values ('Philip', 'Brock');
insert into userName(fcName, fcFrienlyName)values ('Khan', 'Lemy');
declare @Nombres varchar(max);
declare @select varchar(max);
select @Nombres = COALESCE(@Nombres + ',', '') + '[' + fcName + ']'
from userName
group by fcName;
select @select = 'SELECT fiiduserName, ' + @Nombres + '
FROM
(SELECT fiiduserName, fcName, fcFrienlyName
FROM userName) AS SourceTable
PIVOT
(
MIN(fcFrienlyName)
FOR fcName IN (' + @Nombres + ')
) AS PivotTable; '
exec (@select);
drop table userName;
如果你有100多个用户名,你会希望它是动态的,这样你就不必为每个用户名键入特定的CASE语句 此外,您不希望每次向表中添加新用户名时都必须更新脚本 下面的脚本将动态检索所有不同的用户名,并为它们创建一个列,其中包含所有好友的行
DECLARE @cols AS NVARCHAR(MAX), @query AS NVARCHAR(MAX);
SET @cols = STUFF((SELECT distinct ',MAX(CASE WHEN UserName = '''
+ p.UserName + ''' THEN FriendName END) AS '
+ QUOTENAME(p.UserName) FROM Popular p
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET @query = 'SELECT ' + @cols + ' FROM
(SELECT UserName, FriendName
,ROW_NUMBER() OVER (PARTITION BY UserName ORDER BY FriendName) AS RowNum
FROM Popular GROUP BY USERNAME, FRIENDNAME
) x
GROUP BY RowNum'
EXECUTE(@query);
我的上述输出如下所示
╔════════╦══════╦════════╗
║ John ║ Khan ║ Philip ║
╠════════╬══════╬════════╣
║ Jeremy ║ Lemy ║ Brock ║
║ Marry ║ NULL ║ Ursula ║
║ Sarah ║ NULL ║ NULL ║
╚════════╩══════╩════════╝
您应该能够对整个表运行此操作,并获得所有可能用户名的结果,而无需键入单独的CASE语句
对于任何想要测试它的人,这里是测试表和数据脚本
IF EXISTS ( SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'Popular'
AND TABLE_SCHEMA = 'dbo'
AND TABLE_TYPE = 'TABLE')
DROP TABLE [dbo].[Popular];
GO
CREATE TABLE [dbo].[Popular]
(
UserName VARCHAR(20),
FriendName VARCHAR(20)
);
GO
INSERT INTO [dbo].[Popular] (UserName,FriendName) VALUES
('John','Sarah'),
('Philip','Ursula'),
('John','Marry'),
('John','Jeremy'),
('Philip','Brock'),
('Khan','Lemy');
哈桑,这背后的逻辑是什么?到目前为止,你尝试了什么?@BarbarosÖzhan从表输出中可以清楚地看出这一逻辑。他想根据列中的用户名将frields列为行。@ArupRakshit,嗯,你说得对。第一行中没有任何东西将Sarah和Ursula链接起来,你需要通过行号或类似的数字进行匹配。我需要所有列表,而不仅仅是max:@HasanKaanTURAN删除max。生成好友组需要行号。我强烈建议查看PIVOT函数,让显示程序使用第一行作为列名。不要使用这样的解决方案。操作数数据类型nvarchar对于avg运算符无效。我的列具有nvarchar类型您需要为COUNT交换平均值。看起来您在动态查询中缺少分组语句。必须通过添加结束组才能将其正确地添加到组中:选择UserName、FriendName、ROW_NUMBER OVER PARTITION by UserName ORDER by FriendName作为RowNum,从流行的group by UserName中选择RowNum,FriendName xI已经向我的测试表添加了更多数据,直到添加了重复记录,我才发现任何差异。副本现在已删除。谢谢
╔════════╦══════╦════════╗
║ John ║ Khan ║ Philip ║
╠════════╬══════╬════════╣
║ Jeremy ║ Lemy ║ Brock ║
║ Marry ║ NULL ║ Ursula ║
║ Sarah ║ NULL ║ NULL ║
╚════════╩══════╩════════╝
IF EXISTS ( SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'Popular'
AND TABLE_SCHEMA = 'dbo'
AND TABLE_TYPE = 'TABLE')
DROP TABLE [dbo].[Popular];
GO
CREATE TABLE [dbo].[Popular]
(
UserName VARCHAR(20),
FriendName VARCHAR(20)
);
GO
INSERT INTO [dbo].[Popular] (UserName,FriendName) VALUES
('John','Sarah'),
('Philip','Ursula'),
('John','Marry'),
('John','Jeremy'),
('Philip','Brock'),
('Khan','Lemy');