在 1 行中存储动态图像列表
Store a dynamic list of images in 1 row
我正在加入这两个表,我想发送 Test
的视图及其图像。
测试
- 名称 (VARCHAR(255))
- TestId (INT)
- 开始时间 (DATETIME2(7))
- 状态 (VARCHAR(255))
图片
- ImageId (INT)
- TestId (INT)
- 图片 (VARBINARY(MAX))
现在我正在这样做:
SELECT Name, t.TestId, StartTime, Status, Image
FROM [Test] t
LEFT JOIN [Images] i ON i.TestId = t.TestId
我在这里不喜欢的是我有来自同一测试的多行,但图像不同。有没有方便的方法 return 每个测试只有一行及其图像?
我的图像没有那么大(最大 100KB)而且每次测试我没有很多图像(最大 10 张)。这是我的想法:
- 这听起来可能很疯狂,但也许在 SQL 服务器中有一种方法可以将
Image
转换为图像列表作为 VARBINARY(MAX)
- 我可以在视图中有 10 列(image1、image2...)并用图像填充它们(如果它们存在)(NOT NULL)
我不太了解这些解决方案,因为我对 SQL 了解不多,但我仍在尝试。你看到另一种方法吗?如果没有,您能帮我提供有关如何实现 1. 或 2.
的有用建议吗?
第二个选项可以通过 row_number()
和条件聚合来实现,如下所示:
select
t.name,
t.testid,
t.starttime,
t.status,
max(case when i.rn = 1 then i.image end) image01,
max(case when i.rn = 2 then i.image end) image02,
...
max(case when i.rn = 10 then i.image end) image10
from test t
left join (
select testid, image, row_number() over(partition by testid order by imageid) rn
from images
) i on i.testid = t.testid
group by t.name, t.testid, t.starttime, t.status
你也可以使用outer apply
,这样效率会更高:
select
t.*,
i.*
from test t
outer apply (
select
max(case when rn = 1 then image end) image01,
max(case when rn = 2 then image end) image02
...
max(case when rn = 10 then image end) image10
from (
select image, row_number() over(order by imageid) rn
from image i
where i.testid = t.testid
) i
) i
What I don't like here is that I have multiple rows from the same test but with different images.
那又怎样?每行仅重复几个字节,与 100KB 的 blob 相比微不足道。
但是如果您有 SQL 服务器将其转换为 JSON,您可以完全按照您想要的形状检索数据。 varbinary(max) 将被 base64 编码并添加所有 JSON 开销,这将是一个更大的结果大小。但是像
这样的查询
SELECT Name ,
t.TestId ,
StartTime ,
Status ,
(select Image from Images where testid = t.testid for json path) Images
FROM [Test] t
for json path
会输出类似
的数据
[
{
"Name": "Test1",
"TestId": 1,
"StartTime": "2020-04-22T18:15:47.9533333",
"Status": "complete",
"Images": [
{
"Image": "j2LYPy9Uy0Wbz0/qsPk0qo9i2D8vVMtFm89P6rD5NKqPYtg/L1TLRZvPT+qw+TSqj2LYPy9Uy0Wbz0/qsPk0qo9i2D8vVMtFm89P6rD5NKo="
},
{
"Image": "j2LYPy9Uy0Wbz0/qsPk0qo9i2D8vVMtFm89P6rD5NKqPYtg/L1TLRZvPT+qw+TSqj2LYPy9Uy0Wbz0/qsPk0qo9i2D8vVMtFm89P6rD5NKo="
}
]
}
]
我正在加入这两个表,我想发送 Test
的视图及其图像。
测试
- 名称 (VARCHAR(255))
- TestId (INT)
- 开始时间 (DATETIME2(7))
- 状态 (VARCHAR(255))
图片
- ImageId (INT)
- TestId (INT)
- 图片 (VARBINARY(MAX))
现在我正在这样做:
SELECT Name, t.TestId, StartTime, Status, Image
FROM [Test] t
LEFT JOIN [Images] i ON i.TestId = t.TestId
我在这里不喜欢的是我有来自同一测试的多行,但图像不同。有没有方便的方法 return 每个测试只有一行及其图像?
我的图像没有那么大(最大 100KB)而且每次测试我没有很多图像(最大 10 张)。这是我的想法:
- 这听起来可能很疯狂,但也许在 SQL 服务器中有一种方法可以将
Image
转换为图像列表作为VARBINARY(MAX)
- 我可以在视图中有 10 列(image1、image2...)并用图像填充它们(如果它们存在)(NOT NULL)
我不太了解这些解决方案,因为我对 SQL 了解不多,但我仍在尝试。你看到另一种方法吗?如果没有,您能帮我提供有关如何实现 1. 或 2.
的有用建议吗?第二个选项可以通过 row_number()
和条件聚合来实现,如下所示:
select
t.name,
t.testid,
t.starttime,
t.status,
max(case when i.rn = 1 then i.image end) image01,
max(case when i.rn = 2 then i.image end) image02,
...
max(case when i.rn = 10 then i.image end) image10
from test t
left join (
select testid, image, row_number() over(partition by testid order by imageid) rn
from images
) i on i.testid = t.testid
group by t.name, t.testid, t.starttime, t.status
你也可以使用outer apply
,这样效率会更高:
select
t.*,
i.*
from test t
outer apply (
select
max(case when rn = 1 then image end) image01,
max(case when rn = 2 then image end) image02
...
max(case when rn = 10 then image end) image10
from (
select image, row_number() over(order by imageid) rn
from image i
where i.testid = t.testid
) i
) i
What I don't like here is that I have multiple rows from the same test but with different images.
那又怎样?每行仅重复几个字节,与 100KB 的 blob 相比微不足道。
但是如果您有 SQL 服务器将其转换为 JSON,您可以完全按照您想要的形状检索数据。 varbinary(max) 将被 base64 编码并添加所有 JSON 开销,这将是一个更大的结果大小。但是像
这样的查询SELECT Name ,
t.TestId ,
StartTime ,
Status ,
(select Image from Images where testid = t.testid for json path) Images
FROM [Test] t
for json path
会输出类似
的数据[
{
"Name": "Test1",
"TestId": 1,
"StartTime": "2020-04-22T18:15:47.9533333",
"Status": "complete",
"Images": [
{
"Image": "j2LYPy9Uy0Wbz0/qsPk0qo9i2D8vVMtFm89P6rD5NKqPYtg/L1TLRZvPT+qw+TSqj2LYPy9Uy0Wbz0/qsPk0qo9i2D8vVMtFm89P6rD5NKo="
},
{
"Image": "j2LYPy9Uy0Wbz0/qsPk0qo9i2D8vVMtFm89P6rD5NKqPYtg/L1TLRZvPT+qw+TSqj2LYPy9Uy0Wbz0/qsPk0qo9i2D8vVMtFm89P6rD5NKo="
}
]
}
]