Eli*_*298 5 sql-server json sql-server-2014 like date-math
到目前为止,我有以下查询,不幸的是,我无法使用正则表达式或大于运算符,我只能使用LIKE
关键字。
整个列都在 json 字符串中,我无法使用json_value
或 regexp,因为我在 SQL Server 上,所以我只能使用LIKE
. 它是 SQL Server 2014,json_value
直到 2016 年才受支持。
SELECT * FROM DataTableOne
WHERE update_date LIKE '%1645290000%'
Run Code Online (Sandbox Code Playgroud)
我想仅使用 SQL 关键字检索纪元 unix 时间戳大于 1645290000 的所有记录LIKE
(甚至使用 SQLLIKE
运算符在 1645290000 和 9999999999 之间)。
任何帮助将不胜感激,因为这是一个非常困难的独特案例,我只能使用关键字LIKE
。
下面的示例表/数据:
CREATE TABLE DataTableOne (
ID int,
DATA varchar(MAX)
);
INSERT INTO DataTableOne (ID, DATA)
VALUES (1, '{"name":"Cole", "update_date":"2855290000"}'),
(2, '{"name":"Peter", "update_date":"1222290000"}') ;
Run Code Online (Sandbox Code Playgroud)
此类数据可能有一千行,而我只需要 update_date 大于 1645290000 的行。
在我给出的上表上运行查询应该只返回第一行,因为 update_date 2855290000在数字上确实大于 1645290000。
我认为最好将问题分成两部分,找到 update_date 然后使用“>”进行过滤:
select * from DataTableOne
where cast ( substring( data
, charindex('"update_date":', data)+15
, len(data)- (charindex('"update_date":', data)+15) -1 )
as bigint ) > 1645290000
Run Code Online (Sandbox Code Playgroud)
请注意,如果表中存在格式错误的 JSON,查询将会失败。如果是这种情况,您可能希望将提取封装在具有错误处理功能的函数/过程中。
或者,由于TRY_CAST
在 SQL Server 2014 中实现,如果转换失败,将返回 null ,这永远不会满足>
,所以我们可以简单地执行以下操作:
select * from DataTableOne
where TRY_CAST ( substring( data
, charindex('"update_date":', data)+15
, len(data)- (charindex('"update_date":', data)+15) -1 )
as bigint ) > 1645290000;
Run Code Online (Sandbox Code Playgroud)
实际上,如果没有显式 JSON 支持,您不应该在 SQL Server 版本中直接处理 JSON 数据。理想情况下,JSON 源会在导入过程中转换为关系格式。查询数据就变得很容易。
也就是说,如果您确实必须按照您所说的去做,那么有很多选择。
一种是将(简单的)JSON 转换为 XML,然后使用 XQuery:
SELECT
DTO.*
FROM dbo.DataTableOne AS DTO
CROSS APPLY
(
SELECT
TRY_CONVERT(xml,
REPLACE(
REPLACE(
REPLACE(
REPLACE(DTO.[DATA],
'"name":', 'name='),
', "update_date":', ' update_date='),
'{', '<r '),
'}', '/>'))
) AS X (x)
WHERE
1 = X.x.exist('r[1][@update_date ge 1645290000]');
Run Code Online (Sandbox Code Playgroud)
那里没有必要,但在每行[1]
只有一个update_date 的情况下会产生一个稍微好一点的执行计划。
它也几乎可以LIKE
专门使用,但我不推荐它:
SELECT *
FROM dbo.DataTableOne AS DTO
WHERE
DTO.[DATA] COLLATE Latin1_General_BIN2
LIKE '%"update_date":"164529[0-9][0-9][0-9][0-9]"%'
OR DTO.[DATA] COLLATE Latin1_General_BIN2
LIKE '%"update_date":"1645[3-9][0-9][0-9][0-9][0-9][0-9]"%'
OR DTO.[DATA] COLLATE Latin1_General_BIN2
LIKE '%"update_date":"164[6-9][0-9][0-9][0-9][0-9][0-9][0-9]"%'
OR DTO.[DATA] COLLATE Latin1_General_BIN2
LIKE '%"update_date":"16[5-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]"%'
OR DTO.[DATA] COLLATE Latin1_General_BIN2
LIKE '%"update_date":"1[7-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]"%'
OR DTO.[DATA] COLLATE Latin1_General_BIN2
LIKE '%"update_date":"[2-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]"%';
Run Code Online (Sandbox Code Playgroud)
如果您理解LIKE
其中的逻辑,您将能够将其推广到其他值。如果您想解决难题或提出某种类型的问题,这应该可以帮助您入门。