我有一个 1 TB 的数字串。给定一个 12 个字符的数字序列,我想获取该序列在原始字符串(charindex
函数)中的起始位置。
我已经使用 SQL Server 使用 1GB 字符串和 9 位子字符串对此进行了测试,并将字符串存储为varchar(max)
. Charindex
需要 10 秒。将 1GB 字符串分解为 900 字节重叠块并创建一个表(StartPositionOfChunk、Chunkofstring),其中包含二进制排序规则的 chunkofstring,索引时间不到 1 秒。10GB,10 位子字符串的后一种方法将 charindex 提高到 1.5 分钟。我想找到一种更快的存储方法。
数字串:0123456789 - 要搜索的子字符串 345
charindex('345','0123456789') 给出 4
方法 1:我现在可以将其存储在包含一列的 SQL Server 表 strtable 中colstr
并执行:
select charindex('345',colstr) from strtable
Run Code Online (Sandbox Code Playgroud)
方法2:或者我可以通过拆分原始字符串来组成一个表strtable2(pos,colstr1):1;012 | 2;123 | 3;234 aso然后我们可以进行查询
select pos from strtable2 where colstr1='345'
Run Code Online (Sandbox Code Playgroud)
方法 3:我可以通过将原始字符串拆分成更大的块来组成一个表strtable2 (pos2,colstr2) …
sql-server physical-design string-splitting sql-server-2017 string-searching
我正在处理这个确切的堆栈交换部分的数据库转储。在我处理它的过程中,我遇到了一个我目前无法解决的问题。
在 XML 文件 Posts.xml 中,内容如下所示
当然有多行,但这就是一个的样子。转储中已经提供了一个 Tags.xml 文件,这使得该图片中的“Tags”属性实际上应该是它的单独表(多对多)变得更加明显。
所以现在我正试图找出一种如何提取标签的方法。这是我尝试做的:
CREATE TABLE #TestingIdea (
Id int PRIMARY KEY IDENTITY (1,1),
PostId int NULL,
Tag nvarchar (MAX) NULL
)
GO
Run Code Online (Sandbox Code Playgroud)
? 我创建的表来测试我的代码。我已经用标签和 PostIds 填充了它
SELECT T1.PostId,
S.SplitTag
FROM (
SELECT T.PostId,
cast('<X>'+ REPLACE(T.Tag,'>','</X><X>') + '</X>' as XML) AS NewTag
FROM #TestingIdea AS T
) AS T1
CROSS APPLY (
SELECT tData.value('.','nvarchar(30)') SplitTag
FROM T1.NewTag.nodes('X') AS T(tData)
) AS S
GO
Run Code Online (Sandbox Code Playgroud)
然而此代码返回此错误
XML parsing: line 1, character 37, illegal qualified name character …
Run Code Online (Sandbox Code Playgroud) 我有下表,名为商店:
store_id INT
emails VARCHAR
Run Code Online (Sandbox Code Playgroud)
其中包含值:
商店ID | 电子邮件 |
---|---|
1 | user_1@example.com,user2@example.com |
2 | uswe3@example.com,user4@example.com |
4 | admin@example.com |
我想生成以下集合:
商店ID | 电子邮件 |
---|---|
1 | user_1@example.com |
1 | user2@example.com |
2 | uswe3@example.com |
2 | user4@example.com |
4 | admin@example.com |
正如您所看到的,我想将电子邮件字段拆分为仅包含一个电子邮件地址的单独记录。你知道我该怎么做吗?
到目前为止,我成功创建了以下查询:
select store_id,string_to_array(emails,',') from stores
Run Code Online (Sandbox Code Playgroud)
但我不知道如何将其拆分string_to_array
为自己的行。
我有场 id_list='1234,23,56,576,1231,567,122,87876,57553,1216'
我想用它来搜索IN
这个领域:
SELECT *
FROM table1
WHERE id IN (id_list)
Run Code Online (Sandbox Code Playgroud)
id
是 integer
id_list
是 varchar/text
但是这样就行不通了,所以我需要以某种方式拆分id_list
为选择查询。
我应该在这里使用什么解决方案?我正在使用 T-SQL Sybase ASA 9 数据库 (SQL Anywhere)。但是这样就行不通了,所以我需要以某种方式拆分id_list
为选择查询。
我看到的方式是使用while循环创建自己的函数,并根据分隔符位置搜索拆分每个元素提取,然后将元素插入到临时表中,该函数将作为结果返回。
对 Sebastian Meine 回答及其解决方案的评论:
Sybase SQL Anywhere 9
sa_split_list
系统程序在这里不存在,所以它不起作用
CAST
效果很好Sybase SQL Anywhere 12
sa_split_list
系统程序存在并且运行良好
CAST
效果很好对于 Sybase SQL Anywhere 9,我进行了 sa_split_list 系统过程替换:
Run Code Online (Sandbox Code Playgroud)CREATE PROCEDURE str_split_list(in str long varchar, in delim char(10) default ',') RESULT( line_num integer, row_value long varchar) BEGIN DECLARE str2 …
这里我们有两组数字。问题是我无法弄清楚如何从数字的输入到输出(下面的 DDL 和 DML 以及这里的小提琴)。
current_data
1,2,3
1,4
1,5,7
8,9,10
10,11,15
expected_outcome
1,2,3,4,5,7
8,9,10,11,15
Run Code Online (Sandbox Code Playgroud)
我们只是尝试根据单个数字是否与任何其他组匹配来匹配一组数字。然后合并所有这些组。
例如。
如果我们有:
('1,2,3'),
('1,4'),
('1,5,7')
Run Code Online (Sandbox Code Playgroud)
我们想要:
(1,2,3,4,5,7)
Run Code Online (Sandbox Code Playgroud)
我们将它们合并为 PostgreSQL 中的一行。
或(另一个例子):
('8,9,10'),
('10,11,15')
Run Code Online (Sandbox Code Playgroud)
所需的输出:
(8,9,10,11,15)
Run Code Online (Sandbox Code Playgroud)
查询将对这些数字进行分组,因为它们的共同点是数字 10。但它不会与(1,2,3,4,5,7)
不共享数字的前一行(即)分组。
当我们将这些组放在一张表中时。如果他们在每一组中至少有一个匹配的号码,他们才会分组在一起。
======== DDL 和 DML ============
create table current (current_data text not null);
create table expected_output (expected_outcome text not null);
insert into current (current_data) values ('1,2,3'),('1,4'),('1,5,7'),('8,9,10'), ('10,11,15');
insert into expected_output (expected_outcome) values ('1,2,3,4,5,7'),('8,9,10,11,15');
Run Code Online (Sandbox Code Playgroud) 我似乎在对 aSELECT IN
和 a使用硬编码值之间存在巨大的性能差距STRING_SPLIT
。除了最后一个阶段为STRING_SPLIT
代码多次执行索引查找之外,查询计划是相同的。结果是大约 90000 与大约 15000(根据dm_exec_query_stats
)的 CPU 时间,因此差异是巨大的。我已经在这里发布了两个计划......
有趣的是查询计划显示的成本几乎相同,但是当我检查dm_exec_query_stats
成本 ( last_worker_time
)时却大不相同。
这是查询计划的 2 个输出...
0x79DEAD79D1F149CD 16199
select *
from fn_get_samples(1) s
where s.sample_id in
(2495,2496,2497,2498,2499,2500,2501,2502,2503,2504)
0x4A073840486B252C 86689
select *
from fn_get_samples(1) s
where s.sample_id in
(select value as id
from
STRING_SPLIT('2495,2496,2497,2498,2499,2500,2501,2502,2503,2504',','))
Run Code Online (Sandbox Code Playgroud)
功能代码是...
CREATE FUNCTION [dbo].[fn_get_samples]
(
@user_id int
)
RETURNS TABLE
AS
RETURN (
-- get samples
select s.sample_id,language_id,native_language_id,s.source_sentence,s.markup_sentence,s.latin_sentence,
s.translation_source_sentence,s.translation_markup_sentence,s.translation_latin_sentence,
isnull(sample_vkl.knowledge_level_id,1) as vocab_knowledge_level_id,
isnull(sample_gkl.grammar_knowledge_level_id,0) as grammar_knowledge_level_id, …
Run Code Online (Sandbox Code Playgroud) performance sql-server execution-plan string-splitting query-performance
以下查询转换表示 13k 行 x 2 列的打包 CSV 的单个字符串。A 列是一个 bigint。B 列是一个smallint。
declare
@dataCsv nvarchar(max) = '29653,36,19603,36,19604,36,29654,36'; -- abbreviated, actually 13k rows
with Input as
(
select Value,
Row = row_number() over (order by (select null)) - 1
from string_split(@dataCsv, ',') o
)
--insert into PubCache.TableName
select 78064 as CacheId,
convert(bigint, i.Value) as ObjectId,
convert(smallint, i2.Value) as BrandId
from Input i
inner hash join Input i2 -- hash to encourage string_split() only once per column
on i2.Row = i.Row + 1 …
Run Code Online (Sandbox Code Playgroud) SQL 服务器。兼容性级别 120。
我有一个表,其中一个 VARCHAR 列包含以分号分隔的整数值。我想对该列中的值进行 SELECT,就好像它们存在于某处的整数列中一样。
由于兼容级别,我不能使用 STRING_SPLIT。我也无法创建任何全局可用的函数。
但是,如果需要,我可以创建一个临时表。我的行动方针是什么?某种 WHILE 循环的嵌套(一个用于表的行,另一个用于字符串中的分号)?
更新:这可能是我想要实现的更好的解释:
假设我有以下表格。
CREATE TABLE Service
(
ServiceId int
, CustomerIds varchar(255)
);
Run Code Online (Sandbox Code Playgroud)
CREATE TABLE Customer
(
CustomerId int
, CustomerName varchar(30)
);
Run Code Online (Sandbox Code Playgroud)
有一些数据
INSERT INTO Customer (CustomerId, CustomerName)
VALUES (1, 'John')
,(2, 'Niels')
,(3, 'Frank')
,(4, 'Barbie')
,(5, 'Holly')
,(6, 'Ebeneezer');
Run Code Online (Sandbox Code Playgroud)
INSERT INTO Service (ServiceId, CustomerIds)
VALUES (1, '4')
,(2, '2;3');
Run Code Online (Sandbox Code Playgroud)
假设我想为任何客户选择 Customer.CustomerName,该客户的 ID 显示在该表中任何行的 CustomerIds 中。
也就是说,我想检索Niels
,Frank
和Barbie
。
我有一个表,其中每一行都有如下数据:
0150566115,"HEALTH 401K","IC,ON","ICON HEALTH 401K",,,1,08/21/2014
Run Code Online (Sandbox Code Playgroud)
我想要的是删除,
包含在双引号“”之间的每个逗号 ( )。然后用逗号 ( ,
)分割字符串的其余部分
我不想检查双引号开始和结束的每个字符设置标志。
我可以实现某种正则表达式吗?
有没有简单的方法?
到目前为止,我所尝试的只是根据逗号 ( ,
)拆分字符串,但它也在拆分引号内的值。
这是为了达到目的:如何在完整的表中实现这一点(目前,如果我只有一个双引号块实例,它就可以工作)?
Declare @Query nvarchar(max)
Set @Query = 'Item1,Item2,"Item,Demo,3",New'
Declare @start int, @len int
SELECT @start = PATINDEX('%"%"%', @Query) + 1
print @start
select @len = CHARINDEX('"', SUBSTRING(@Query, @start, LEN(@Query))) - 1
select
SUBSTRING(@Query, 1, @start - 2) +
REPLACE((SUBSTRING(@Query, @start, @len)), ',', '') +
SUBSTRING(@Query, @start + @len + 1, LEN(@Query))
Run Code Online (Sandbox Code Playgroud)
这是我用来分割的函数
ALTER FUNCTION [dbo].[fnSplit](
@sInputList VARCHAR(8000) -- List of …
Run Code Online (Sandbox Code Playgroud) sql-server ×6
t-sql ×3
postgresql ×2
array ×1
performance ×1
string ×1
sybase ×1
xml ×1
xquery ×1