交叉应用使用的子查询不返回结果
Posted
技术标签:
【中文标题】交叉应用使用的子查询不返回结果【英文标题】:Cross Apply used Sub Query not Return Result 【发布时间】:2020-12-11 07:25:29 【问题描述】:我想从deviceinfo
列中提取版本数据。为此,我使用 交叉应用。
Order
----------------------------------
OrdeId DeviceInfo
----------------------------------
10 PageSize|BGColor|3000|V1.0
11 PageSize|BGColor|3000|V2.0
12 PageSize|BGColor|3000|V3.0
----------------------------------
我使用了以下查询
Select * From
(
Select OrderId, DeviceInfo, Value, ROW_NUMBER() Over(Partition By DeviceInfo Order By OrderId Asc) As Rn
FROM Order As Ord
Cross Apply STRING_SPLIT(DeviceInfo, '|') As Di
Where IsNull(Ord.DeviceInfo,'') != '' And OrderId='10'
)A Where A.Rn=4 And A.OrderId='10'
我得到了结果。
OrderId DeviceInfo Value Rn
------------------------------------------------
10 PageSize|BGColor|3000|V1.0 V1.0 4
如果我在子查询中使用没有 orderid 过滤器的查询,我会得到 空结果。
Select * From
(
Select OrderId, DeviceInfo, Value, ROW_NUMBER() Over(Partition By DeviceInfo Order By OrderId Asc) As Rn
FROM Order As Ord
Cross Apply STRING_SPLIT(DeviceInfo, '|') As Di
Where IsNull(Ord.DeviceInfo,'') != ''
)A Where A.Rn=4 And A.OrderId='10'
请帮我解决这个问题
【问题讨论】:
你想要的结果是什么?使用 ROW_NUMBER,您只会得到一个结果(每个 DeviceInfo),即 OrderId 最低的结果。如果不过滤子查询,会得到 OrderId 的 我运行了您的两个示例查询,它们返回完全相同的结果集。您能否尝试重新解释您看到的问题并提供任何错误。 请不要在 WHERE 部分的列上使用函数。这可能对性能不利。更好地使用Ord.DeviceInfo IS NOT NULL OR Ord.DeviceInfo != ''
@gofr1 在这种情况下,他们希望忽略 NULL 和空白。所以应该是AND
。然而,他们在技术上只需要WHERE Ord.DeviceInfo <> ''
,空值会被自动过滤掉
【参考方案1】:
对意外结果的可能解释是以下问题的组合:
在ROW_NUMBER()
函数调用中错误使用PARTITION BY
和ORDER BY
子句。 ROW_NUMBER() Over (Partition By DeviceInfo Order By OrderId Asc)
以随机和意外的顺序编号行。
使用STRING_SPLIT()
按位置提取子字符串是一个棘手的方法。正如文档中的mentioned 一样,输出行可能是任何顺序,并且不保证该顺序与输入字符串中子字符串的顺序相匹配。
在您的情况下(如果您想按位置提取子字符串),您可以尝试使用基于 JSON 的方法来解析 DeviceInfo
列。您需要将数据转换为有效的 JSON 数组(PageSize|BGColor|3000|V1.0
转换为 ["PageSize","BGColor","3000","V1.0"]
)并使用 OPENJSON()
解析该数组。 OPENJSON()
调用的结果是一个包含 key
、value
和 type
列的表,key
列保存指定数组中元素的从 0 开始的索引。
表:
CREATE TABLE [Order] (
OrderId int,
DeviceInfo varchar(1000)
)
INSERT INTO [Order] (OrderId, DeviceInfo)
VALUES
(10, 'PageSize|BGColor|3000|V1.0'),
(11, 'PageSize|BGColor|3000|V2.0'),
(12, 'PageSize|BGColor|3000|V3.0')
声明:
SELECT OrderId, DeviceInfo, [Value]
FROM [Order] AS o
CROSS APPLY OPENJSON(CONCAT('["', REPLACE(o.DeviceInfo, '|', '","'), '"]')) AS j
WHERE o.OrderId = 10 AND j.[key] = '3'
结果:
OrderId DeviceInfo Value
----------------------------------------
10 PageSize|BGColor|3000|V1.0 V1.0
【讨论】:
确保您的字符串不包含任何逗号 (,
)。
@F***Pijcke 逗号 (,
) 不是问题。双引号 ("
) 是一个可能的问题,但如果 OP 使用 SQL Server 2017+,REPLACE(STRING_ESCAPE(o.DeviceInfo, 'json'), '|', '","')
可以解决此问题。以上是关于交叉应用使用的子查询不返回结果的主要内容,如果未能解决你的问题,请参考以下文章