2016-12-30 1 views
1

Ich versuche derzeit, die aktuelle Stichwortsuche zu überarbeiten, die ich in die Scripting-Software, die wir verwenden (die alte war sehr einfach und umständlich) zu etwas mehr verfeinert. Es gibt Beschränkungen für die Software, die wir verwenden, und die IT ist gebunden, so dass ich nicht die Möglichkeit habe, eine Funktion oder eine gespeicherte Prozedur zu erstellen, von der ich denke, dass sie die ideale Lösung wäre.Verwenden eines Falles, um numerische Werte zuzuweisen und durch den höchsten Wert

Die Situation ist, dass der Endbenutzer möglicherweise ein generisches Skript verwendet, wenn sie ein bestimmtes Skript für ihr Problem verwenden sollten, also möchte ich SQL erstellen, die erkennt, ob sie mit einem anderen Skript gegangen sein sollten Schlagwortsuche.

Ich habe eine Liste von Wörtern mit jedem Skript zugeordnet Ich fühle mich sollten sie beispielsweise Verwendung:

Reparatur Skript Schlüsselwörter: Reparatur, gebrochen, jagen

Immobilien Skript Schlüsselwörter: schmutzig, Reinigung , Garten

Was ich tun möchte, ist, etwas SQL zu machen, das jedem Exemplar dieser Wörter innerhalb der Datenbank '{Script.Details}}' einen numerischen Wert von 1 zuweist und dann herausfindet, welcher Satz von Schlüsselwörtern das hat höchste Tally am Ende.

Das ist, was ich bis jetzt müde habe, ich weiß, dass es wegen der Syntax wahrscheinlich nicht funktioniert. Leider ist die Software, die wir benutzen, ziemlich vage, wenn man Fehlermeldungen gibt, so dass es nicht viel hilft. Wir verwenden Aliase von V und D. D ist die Benutzeranzeige, also was sie physikalisch sehen, V ist der Wert, den das System liest und der Benutzer nicht sieht. Die Datenbox, in der sich die gesuchte Zeichenfolge befindet, lautet '{Script.Details01}'. Da diese Informationen virtuell in der Software gespeichert sind, müssen wir nicht das FROM-Feld verwenden, wie wir es normalerweise tun würden, wenn wir auf diesen Ort verweisen.

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 

Wesentlichen, was ich für den Code bin auf der Suche zu tun ist, um mir zu sagen, ob es eine höhere tally für REP ist (Reparatur) und EST (estate) oder, wenn es keine Werte eingetragen gegen entweder sind. Entschuldigung, wenn ich das nicht gut erklärt habe, gibt es ein paar Einschränkungen innerhalb der Software, die wir verwenden, und versuche es so gut wie möglich zu erklären. Irgendwelche Ideen würden sehr geschätzt werden.

+0

vergessen zu erwähnen, Informationen in diesem Details01 databox eine Zeichenfolge sein könnte wie: „Anrufer wollen, über die Reparatur beschweren sie für Tage haben zu jagen, als ihre Kessel ist kaputt". Ich möchte, dass dies als "Needing" durchgeht, um zum Reparaturskript zu gehen. –

+1

Bitte fügen Sie passende Tags für DBRMS und Version hinzu. – user1429080

+0

Entschuldigung, die Software, die wir verwenden, heißt Keyfax, aber es ist keine allgemein verwendete Software, aber es referenziert SQL Server 2012, ich habe die Tags jetzt entsprechend aktualisiert –

Antwort

2

Hier ist ein erster Stich zu lösen, in gewissem Maße. Es verwendet ein CTE, die in Ihrem Fall könnte oder nicht durchführbar sein könnte:

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 

Hinweis: Die CTE eine Adaption eines CTE in diesem answer ist.

Was macht es eigentlich? Es verwendet die CTE, um den Eingabetext in einzelne Wörter aufzuteilen, dann sucht er nach den gegebenen Schlüsselwörtern und führt eine Zählung durch. Die Ausgabe von Beispiel:

+-----+-----+-------+ 
| rep | est | other | 
+-----+-----+-------+ 
| 4 | 1 | 16 | 
+-----+-----+-------+ 

So hat es ein Schlüsselwort gefunden, die zur Estate Gruppe gehört, 4 Schlüsselwörter aus der Repair Gruppe, und 16 andere.

Um die Probe für Ihren Anwendungsfall anzupassen, ersetzen Sie @inputText durch '{Script.Details01}'.

--- EDIT ---

Versuchen Sie dies dann:

;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 

Ausgang:

+------------+-----------+ 
| scriptType | typeCount | 
+------------+-----------+ 
| rep  |   4 | 
+------------+-----------+ 

--- ONE MORE EDIT, Wildcard Suche ---

Ersetzen

select case when DataItem in ('repair','broken','chasing') then 'rep' when DataItem in ('dirty','cleaning','garden') then 'est' else '' end as scriptType, 

mit

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, 
+0

danke, dass Sie sich die Zeit genommen haben, sich das zu überlegen. Ich war mir CTEs vorher nicht bewusst, ich bin noch relativ neu in SQL und habe die ganze Zeit gelernt. Das klingt, als wäre es das, was ich brauche. Eine der Einschränkungen der Software ist jedoch, dass mehrere Zeilen nicht angezeigt werden können. Daher muss ich nur das Ergebnis mit der höchsten Anzahl ziehen, wobei die Gesamtzahl der Wörter unberücksichtigt bleibt. Ich nehme an, dies würde eine SELECT TOP 1 irgendwo im Code enthalten, aber nicht sicher, wo dies mit dieser Syntax sitzen würde? –

+0

@CraigJones Siehe Update – user1429080

+0

Sie werden schnell zum Helden des Tages! Sehr nah am Endergebnis, das ich suche. Ich habe den letzten Abschnitt gelöscht, da ich zur Zeit keine Zählung für die anderen Wörter verwende, jetzt muss ich nur noch wählen, welche die höchste Zählung hat und nur diese anzeigen und welche Spalte in Bezug steht. Ich werde ein Stück damit herumspielen, da ich ein bisschen mehr darüber verstehe, wie diese Aussage konstruiert wird –

2

Ich weiß nicht, ob Sie die Schlüsselwörter in der Datenbank speichern können, aber das wäre imho über harte Codierung vorzuziehen. Auf diese Weise können Sie die Pflege der Schlüsselwörter außerhalb der Funktion beibehalten. Die T-SQL unten funktioniert wie es ist, aber die Keyword-Tabelle kann sich stattdessen auf die db portiert werden:

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 

Für jedes Wort in der Tabelle, ein wie ausgeführt (Platzhalter innerhalb der Worte verwendet werden können, wie Gut). Die group by prüft die Anzahl der Vorkommen für jeden Typ und die order by und top 1 stellen Sie sicher, dass Sie nur die mit den meisten Vorkommen erhalten (Sie könnten eine zusätzliche Schwerkraft hinzufügen, wenn beide Typen die gleiche Anzahl von Vorkommen haben)

bearbeiten Da in der db Speicherung ist keine Option: das gleiche kann auch ohne Tisch variabel erfolgen:

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 
+0

Danke dafür. Leider habe ich keinen Zugang dazu. Im Wesentlichen ist meine Rolle nicht ganz IT, und in einer idealen Situation würde ich etwas wie dieses verwenden (was ich weiß, ist viel einfacher und elegant!), Aber unsere IT-Ressource ist derzeit so dünn gestreckt, dass solche Dinge einfach nicht erledigt werden, also versuchen, proaktiv zu sein und Lösungen zu finden. Ich schätzte die Aussage über das Verfolgen von Autos, aber brachte mich zum Lachen. –

+0

Der Code kann unverändert verwendet werden. Ich wollte nur die Idee erwähnen, es in die Datenbank zu portieren. Und konnte nicht widerstehen, einen Satz mit allen Wörtern zu machen: p –

+0

Sie sind richtig! Ich wusste nicht, dass du es auf diese Weise als temporären Tisch einrichten könntest. SQL = 'ManyWaysToSkinACat'. Ich habe mich gefragt, ob es einen Weg gibt, um nur die Spaltenüberschrift mit der höchsten Anzahl anzuzeigen, dh nur Rep oder EST? Versucht, wie ich dies normalerweise tun würde und es scheint, die Bindung von K.Type und K.Word –

0

die Sie interessieren, beachten Sie, dass ich für alle Keywords einen Beispieltext haben . Sie müssen diese mit dem ersetzen Sie haben:

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 @[email protected]+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 @[email protected]+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 @[email protected]+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 @[email protected]+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 @[email protected]+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 @[email protected]+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; 
Verwandte Themen