Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server SQL Server将前两行连接为两列_Sql Server_Subquery - Fatal编程技术网

Sql server SQL Server将前两行连接为两列

Sql server SQL Server将前两行连接为两列,sql-server,subquery,Sql Server,Subquery,我有两张桌子: 表用户: Id, Name, Email,... 表图像: UserId, Priority, Path,... 我想创建一个用户视图,每个用户都有两个具有最高优先级的图像,结果如下: User.Id, User.Name, User.Email, Image1, Image2 ------------------------------------------------- 我假设,如果用户没有图像,则Image1和Image2两列都将NULL,如果只有一个图像,则将设置

我有两张桌子:

用户

Id, Name, Email,...
图像

UserId, Priority, Path,...
我想创建一个用户视图,每个用户都有两个具有最高优先级的图像,结果如下:

User.Id, User.Name, User.Email, Image1, Image2
-------------------------------------------------
我假设,如果用户没有图像,则
Image1
Image2
两列都将
NULL
,如果只有一个图像,则将设置
Image1
,并且
Image2
NULL


我如何才能最有效地实现这一点?我指的是数据库性能。

将这些示例模式/数据用作模型:

CREATE TABLE #User (Id INT, Name VARCHAR(MAX), Email VARCHAR(MAX))
CREATE TABLE #Images (UserId INT, [Priority] INT, [Path] VARCHAR(MAX))
INSERT INTO #User VALUES
(1, 'Bob', 'bob@foo.com'),
(2, 'Jim', 'jim@foo.com')

INSERT INTO #Images VALUES
(1, 10, 'path1'),
(1, 5, 'path2'),
(1, 7, 'path3')
您可以使用
PIVOT

SELECT UserId, [1] AS PathOfImage1, [2] AS PathOfImage2
FROM 
(SELECT UserId, [Path], 
        ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY [Priority] DESC) AS rn
 FROM #Images ) AS source
 PIVOT 
 (
   MAX([Path])
   FOR rn IN ([1], [2])
 ) AS pvt
SELECT t.UserId, 
       [PathOfImage1] = MAX(CASE WHEN rn = 1 THEN [Path] ELSE NULL END),
       [PathOfImage2] = MAX(CASE WHEN rn = 2 THEN [Path] ELSE NULL END),
       [PriorityOfImage1] = MAX(CASE WHEN rn = 1 THEN [Priority] ELSE NULL END),
       [PriorityOfImage2] = MAX(CASE WHEN rn = 2 THEN [Priority] ELSE NULL END)
FROM (
  SELECT UserId, [Path], [Priority],
         ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY [Priority] DESC) AS rn
  FROM #Images ) t
GROUP BY t.UserId
要在单个记录中获取每个用户的前两个图像,请执行以下操作:

UserId  PathOfImage1    PathOfImage2
------------------------------------
1       path1           path3
请注意,
Id=2
的用户不会出现在上述结果集中,因为他没有任何相关图像

现在,您可以对上述查询生成的表表达式执行和
OUTER APPLY

SELECT u.Id, u.Name, Images.PathOfImage1, Images.PathOfImage2
FROM #User u
OUTER APPLY (
   SELECT UserId, [1] AS PathOfImage1, [2] AS PathOfImage2
   FROM (
      SELECT UserId, [Path], 
             ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY [Priority] DESC) AS rn
      FROM #Images ) AS source
   PIVOT 
   (
      MAX([Path])
      FOR rn IN ([1], [2])
   ) AS pvt
   WHERE UserId = u.Id
) Images
为了获得所需的输出:

Id  Name    PathOfImage1    PathOfImage2
----------------------------------------
1   Bob     path1           path3
2   Jim     NULL            NULL
编辑:

如果应从
Image
表中拉出多个列,则必须将
PIVOT
替换为旧式条件聚合,因为SQL Server不支持
PIVOT
上的多个聚合:

SELECT UserId, [1] AS PathOfImage1, [2] AS PathOfImage2
FROM 
(SELECT UserId, [Path], 
        ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY [Priority] DESC) AS rn
 FROM #Images ) AS source
 PIVOT 
 (
   MAX([Path])
   FOR rn IN ([1], [2])
 ) AS pvt
SELECT t.UserId, 
       [PathOfImage1] = MAX(CASE WHEN rn = 1 THEN [Path] ELSE NULL END),
       [PathOfImage2] = MAX(CASE WHEN rn = 2 THEN [Path] ELSE NULL END),
       [PriorityOfImage1] = MAX(CASE WHEN rn = 1 THEN [Priority] ELSE NULL END),
       [PriorityOfImage2] = MAX(CASE WHEN rn = 2 THEN [Priority] ELSE NULL END)
FROM (
  SELECT UserId, [Path], [Priority],
         ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY [Priority] DESC) AS rn
  FROM #Images ) t
GROUP BY t.UserId

谢谢,不用锋利的工具也能用。顺便问一下,为什么表名中有一个sharp。有什么特别的吗?@qub1n
#
符号用于表示临时表。在发布查询之前,我不得不模拟一些示例数据来测试我的查询,临时表是一种快速的方法。好啊谢谢。@qub1n您也可以尝试用
左连接替换
OUTER APPLY
,看看这两种连接在性能上的比较。我正在玩这段代码,试图增加图像的高度和宽度。你能给我一个提示吗?我已经将所有字段放入MAX(ServerPath、Height、Width),但它似乎是错误的。。。。