我目前正在尝试彻底检查我在我们使用的脚本软件中使用的当前关键字搜索(旧版本是基本的和繁琐的)以更精致的方式。我们使用的软件存在一些限制,而且IT也很紧张,所以我没有创建功能或存储过程的选项,我认为这是理想的解决方案。
最终用户可能正在使用通用脚本,当他们应该针对他们的问题使用特定脚本时,所以我想创建一些SQL来检测他们是否应该使用关键字转到不同的脚本搜索。
我有一个与我认为应该使用的每个脚本相关联的单词列表,例如:
修复脚本关键字: 修理,破碎,追逐
遗产脚本关键字: 脏,清洁,花园
我想要做的是在数据库'{Script.Details01}'中为这些单词的每个实例创建一个数值为1的SQL,然后确定哪个关键字具有最高的关键字结束。
到目前为止,这是我累了,我知道由于语法原因,它可能无法正常工作。可悲的是,我们使用的软件在提供错误消息时非常模糊,所以它没有多大帮助。我们使用的是V和D的别名.D是用户显示,因此他们实际看到的是,V是系统读取的值,用户看不到。我们正在搜索的字符串的数据堆是'{Script.Details01}'。由于这些信息几乎存储在软件中,因此我们不必像引用此位置时那样使用FROM字段。
SELECT 'GO TO DIFFERENT SCRIPT' D, 'GO TO DIFFERENT SCRIPT' V,
CASE WHEN EXISTS(SELECT '{Script.Details01}' WHERE '{Script.Details01}' like '%repair%') THEN 1 ELSE 0 END +
CASE WHEN EXISTS(SELECT '{Script.Details01}' WHERE '{Script.Details01}' like '%broken%') THEN 1 ELSE 0 END +
CASE WHEN EXISTS(SELECT '{Script.Details01}' WHERE '{Script.Details01}' like '%chasing%') THEN 1 ELSE 0 END AS REP
CASE WHEN EXISTS(SELECT '{Script.Details01}' WHERE '{Script.Details01}' like '%dirty%') THEN 1 ELSE 0 END +
CASE WHEN EXISTS(SELECT '{Script.Details01}' WHERE '{Script.Details01}' like '%cleaning%') THEN 1 ELSE 0 END +
CASE WHEN EXISTS(SELECT '{Script.Details01}' WHERE '{Script.Details01}' like '%garden%') THEN 1 ELSE 0 END AS EST
WHERE REP = (SELECT MAX(REP)) AND REP <> 0 AND > EST
OR EST = (SELECT MAX(EST)) AND EST <> 0 AND > REP
基本上我正在寻找的代码是告诉我REP(修复)和EST(遗产)是否有更高的标记,或者是否没有注册任何值。抱歉,如果我没有解释清楚,我们正在使用的软件中有一些限制,所以我尽力解释它。任何想法都将不胜感激。
答案 0 :(得分:2)
这是在某种程度上解决这个问题的第一次尝试。它使用CTE
,在您的情况下可能会或可能不可行:
declare @inputText nvarchar(2000)
set @inputText = 'Caller wanting to complain about the repair they have chasing for days, as their boiler is garden broken and needs repair'
--------
declare @inputText nvarchar(2000)
set @inputText = 'Caller wanting to complain about the repair they have chasing for days, as their boiler is garden broken and needs repair'
;with SplitIntoWords(DataItem, Data) as (
select cast(LEFT(@inputText, CHARINDEX(' ', @inputText + ' ') - 1) as nvarchar(2000)),
cast(STUFF(@inputText, 1, CHARINDEX(' ', @inputText + ' '), '') as nvarchar(2000))
union all
select cast(LEFT(Data, CHARINDEX(' ', Data + ' ') - 1) as nvarchar(2000)),
cast(STUFF(Data, 1, CHARINDEX(' ', Data + ' '), '') as nvarchar(2000))
from SplitIntoWords
where Data > ''
)
select (
select count(*) from SplitIntoWords where DataItem in ('repair','broken','chasing')
) as rep,
(
select count(*) from SplitIntoWords where DataItem in ('dirty','cleaning','garden')
) as est,
(
select count(*) from SplitIntoWords where DataItem not in ('dirty','cleaning','garden','repair','broken','chasing')
) as other
注意:CTE
是此answer中CTE
的改编。
那它实际上做了什么?它使用CTE
将输入文本拆分为单个单词,然后搜索给定的关键字并执行计数。样本输出:
+-----+-----+-------+
| rep | est | other |
+-----+-----+-------+
| 4 | 1 | 16 |
+-----+-----+-------+
因此,它找到了1个关键字属于Estate
组,4个关键字来自Repair
组,还有16个关键字。
要根据您的使用案例调整样本,请将@inputText
替换为'{Script.Details01}'
。
---编辑---
然后试试这个:
;with SplitIntoWords(DataItem, Data) as (
select cast(LEFT(@inputText, CHARINDEX(' ', @inputText + ' ') - 1) as nvarchar(2000)),
cast(STUFF(@inputText, 1, CHARINDEX(' ', @inputText + ' '), '') as nvarchar(2000))
union all
select cast(LEFT(Data, CHARINDEX(' ', Data + ' ') - 1) as nvarchar(2000)),
cast(STUFF(Data, 1, CHARINDEX(' ', Data + ' '), '') as nvarchar(2000))
from SplitIntoWords
where Data > ''
)
select top 1 scriptType, count(*) as typeCount
from (
select case when DataItem in ('repair','broken','chasing') then 'rep' when DataItem in ('dirty','cleaning','garden') then 'est' else '' end as scriptType,
DataItem
from SplitIntoWords
) as sub
where scriptType != ''
group by scriptType
order by count(*) desc
输出:
+------------+-----------+
| scriptType | typeCount |
+------------+-----------+
| rep | 4 |
+------------+-----------+
---一个更多的编辑,通配符搜索---
替换
select case when DataItem in ('repair','broken','chasing') then 'rep' when DataItem in ('dirty','cleaning','garden') then 'est' else '' end as scriptType,
与
select
case when
DataItem like '%repair%'
or DataItem like '%broken%'
or DataItem like '%chasing%' then 'rep'
when
DataItem like '%dirty&'
or DataItem like '%cleaning%'
or DataItem like '%garden%' then 'est'
else '' end as scriptType,
答案 1 :(得分:2)
我不知道您是否可以将关键字存储在数据库中,但这比硬编码更可取。这样你就可以将关键字的维护保留在函数之外。 下面的t-sql按原样工作,但关键字表可以移植到db本身:
declare @keywords table(word varchar(50), type varchar(10)) --preferrably when stored in db, the type would be normalized to another table
insert into @keywords values
('repair', 'Rep'),
('broken', 'Rep'),
('chasing', 'Rep'),
('dirty', 'EST'),
('cleaning', 'EST'),
('garden', 'EST')
declare @teststring varchar(512) = 'When the film "chasing cars" was broken, we tried to repair it. It turned out it was dirty from lying in the garden, so we gave it a thorough cleaning'
select top 1 k.type, COUNT(1) cnt from @keywords k where @teststring like '%' + k.word + '%' group by k.type order by COUNT(1) desc
对于表格内的每个单词,都会执行类似的操作(也可以在单词内使用通配符)。 group by
检查每种类型的出现次数,order by
和top 1
确保只获得最多次出现次数(您可以为要排序的类型添加额外的重力) ,如果两种类型的出现次数相同)
修改强> 由于在db中存储不是一个选项:同样也可以在没有表变量的情况下完成:
select top 1 k.type from (values
('repair', 'Rep'),
('broken', 'Rep'),
('chasing', 'Rep'),
('dirty', 'EST'),
('cleaning', 'EST'),
('garden', 'EST')
) k(word,type)
where @teststring like '%' + k.word + '%' group by k.type order by COUNT(1) desc
答案 2 :(得分:0)
试试这个,请注意我有每个关键字的示例文字。你需要用你的那个替换它们:
DECLARE @repairtext AS varchar(max);
SET @repairtext = 'repair, broken, chasing, garden dirty, cleaning, garden'
DECLARE @repair int,@RepairCounter int
SET @repair= PATINDEX('%repair%',@repairtext)
IF @repair<>0 SET @Repaircounter=1
WHILE @repair<>0
BEGIN
SET @repairtext = STUFF(@repairtext,1,@repair+6,'')
SET @repair= PATINDEX('%repair%',@repairtext)
IF @repair<>0 SET @RepairCounter=@RepairCounter+1
END;
DECLARE @brokentext AS varchar(max);
SET @brokentext = 'repair, broken, chasing, garden dirty, cleaning, garden'
DECLARE @broken int,@BrokenCounter int
SET @broken= PATINDEX('%broken%',@brokentext)
IF @broken<>0 SET @BrokenCounter=1
WHILE @broken<>0
BEGIN
SET @brokentext = STUFF(@brokentext,1,@broken+6,'')
SET @broken= PATINDEX('%broken%',@brokentext)
IF @broken<>0 SET @BrokenCounter=@BrokenCounter+1
END;
DECLARE @chasingtext AS varchar(max);
SET @chasingtext = 'repair, broken, chasing, garden dirty, cleaning, garden'
DECLARE @chasing int,@chasingCounter int
SET @chasing= PATINDEX('%chasing%',@chasingtext)
IF @chasing<>0 SET @chasingCounter=1
WHILE @chasing<>0
BEGIN
SET @chasingtext = STUFF(@chasingtext,1,@chasing+7,'')
SET @chasing= PATINDEX('%chasing%',@chasingtext)
IF @chasing<>0 SET @chasingCounter=@chasingCounter+1
END;
DECLARE @dirtytext AS varchar(max);
SET @dirtytext ='repair, broken, chasing, garden dirty, cleaning, garden'
DECLARE @dirty int,@dirtyCounter int
SET @dirty= PATINDEX('%dirty%',@dirtytext)
IF @dirty<>0 SET @dirtyCounter=1
WHILE @dirty<>0
BEGIN
SET @dirtytext = STUFF(@dirtytext,1,@dirty+5,'')
SET @dirty= PATINDEX('%dirty%',@dirtytext)
IF @dirty<>0 SET @dirtyCounter=@dirtyCounter+1
END;
DECLARE @cleaningtext AS varchar(max);
SET @cleaningtext = 'repair, broken, chasing, garden dirty, cleaning, garden'
DECLARE @cleaning int,@cleaningCounter int
SET @cleaning= PATINDEX('%cleaning%',@cleaningtext)
IF @cleaning<>0 SET @cleaningCounter=1
WHILE @cleaning<>0
BEGIN
SET @cleaningtext = STUFF(@cleaningtext,1,@cleaning+8,'')
SET @cleaning= PATINDEX('%cleaning%',@cleaningtext)
IF @cleaning<>0 SET @cleaningCounter=@cleaningCounter+1
END;
DECLARE @gardentext AS varchar(max);
SET @gardentext = 'repair, broken, chasing, garden dirty, cleaning, garden'
DECLARE @garden int,@gardenCounter int
SET @garden= PATINDEX('%garden%',@gardentext)
IF @garden<>0 SET @gardenCounter=1
WHILE @garden<>0
BEGIN
SET @gardentext = STUFF(@gardentext,1,@garden+6,'')
SET @garden= PATINDEX('%garden%',@gardentext)
IF @garden<>0 SET @gardenCounter=@gardenCounter+1
END;
DECLARE @REP int = @RepairCounter + @BrokenCounter + @chasingCounter
,@EST int = @dirtyCounter + @cleaningCounter + @gardenCounter;
IF @REP > @EST
SELECT @REP AS REP
ELSE IF @REP < @EST
SELECT @EST AS EST
ELSE SELECT @REP AS REP;