2016-05-18 18 views
2

Ich werde versuchen, mit einem erklären zu erklären, weil es etwas kompliziert ist. Ich möchte Wörter aus meiner SQL-Tabelle entfernen, wenn das Wortstamm bereits in der Tabelle vorhanden ist. So ist meine Tabellenstruktur wie dieseWie bestimmte Wörter in der Datenbank entfernen?

Words Scores 
car  5 
book  11 
cars  2 
pen  10 
tool  4 
car's  8 
tools  2 

So in diesem Fall, da Auto Wurzel des Autos und Autos, Werkzeug Wurzel von Werkzeugen ist, würde Ich mag, sie entfernen und ihre Gäste auf dem Stammwort hinzufügen und mein Tisch so;

Words Scores 
car  15 
book  11 
pen  10 
tool  6 

nicht: Wenn es „a“ in der Liste enthalten ist, werden alle Wörter, die mit einem gehen beginnen zu entfernen; denn das dachte ich darüber, dass, wenn die Bedingung wie; if (string[i].Length>=3) aber natürlich wird es nicht alle Möglichkeiten meiden, vielleicht wird es Wort "buchen" und "Buchung" geben, so dass Buchung gelöscht wird, aber es ist OK.

+0

Welche dbms verwenden Sie ?? – sagi

+1

sehr gut gefragt. Interessante Frage. –

+1

hm, das ist eine interessante Frage. ABER: Es ist keine SQL-Frage. Du brauchst eine Art Grammatik/Zauber/Rede/was auch immer-Werkzeug, um zu prüfen, ob ein Wort eine Wurzel eines anderen Wortes ist. Sie können dies nicht via SQL entscheiden. Sobald Sie wissen, welche Wörter Wurzeln sind und nicht, können Sie Ihren Tisch aktualisieren. – swe

Antwort

3

Nun, ich kann mir keine einfachere Lösung vorstellen, wenn Sie keine Beziehungstabelle mit root und childs haben, aber Sie können so etwas versuchen - In zwei Schritten, ersten Schritt aktualisieren Sie die Ergebnisse, die zweite löschen Sie die Kinder:

UPDATE YourTable t 
SET t.Scores =(SELECT sum(s.scores) FROM YourTable s 
       WHERE s.words like concat('%',t.words,'%')) 

EDIT: oder diese

update t 
set t.score=sum(s.score) 
from YourTable t 
INNER JOIN YourTable s 
ON (s.words like concat('%',t.words,'%')) 

Dies wird jeder auf ihre childs (gleich aussehen) Gesamtscore aktualisieren.

löschen Dann:

DELETE FROM YourTable t 
WHERE t.words in(SELECT s.words FROM YourTable s 
       WHERE t.words like concat('%',s.words,'%') 
       AND t.words <> s.words) 

Diese alle Datensätze löschen wird, die ein Kind (gleich aussehen) eines anderen Wortes sind. Es wird sich nicht auf DBMS arbeiten, hier so ist eine andere Version davon mit einem Join (Update-Join-Syntax unterscheidet sich von einem zum anderen db):

DELETE FROM YourTable t 
INNER JOIN YourTable s 
ON(t.words like concat('%',s.words,'%') 
    AND t.words <> s.words) 

Sie haben Ihre RDBMS nicht bieten, so ist dies eine Antwort für ANSI-SQL. Dies ist nicht getestet, also überprüfen Sie, ob es funktioniert.

Bearbeiten: Bedenke, dass es ohne eine root-child-Tabelle einige Ausnahmen geben wird, die nicht funktionieren und zu unnötiger Aktualisierung/Löschung führen können. Sie müssen Regeln machen, wann ein Wort ein Kind eines anderen Wortes ist, das keine Erwartung haben wird (ich weiß nicht, ob es überhaupt möglich ist, sql zu benutzen).

Mein bester Vorschlag - füllen Sie selbst solche Tabelle, fügen Sie alle root-Kind-Optionen, und verwenden Sie diese Tabelle für die Löschung/Aktualisierung, damit keine Fehler gemacht werden.

+0

danke für die Antwort, wenn ich Code in mein Projekt wie folgt implementiert haben http://dpaste.com/2P73MT4 Ich habe eine Fehlermeldung erhalten. Der Operator '%' kann nicht auf Operanden vom Typ 'string' und 'string' angewendet werden. –

+0

@infoporto Sie haben einen Fehler dort, Sie haben doppelte Anführungszeichen für den zweiten '%' – sagi

+0

, danke nochmal, ich habe es http: // dpaste behoben. com/1SF6VB5, aber ich bekomme einen Fehler, der sagt; Falsche Syntax in der Nähe von 't'. für die Zeile 136: cmv.ExecuteNonQuery(); Ist es falsch exuutenonquery für diese sql-Anweisung zu verwenden? –

1

Hier ist ein Anfang, der einige häufige Fälle findet. Es ist sinnvoll, als ersten Schritt nur Wörter mit 3 oder mehr Zeichen zu berücksichtigen.

select distinct w2.word from words w inner join words w2 
on w.word = w2.word + 's' 
    or w.word = w2.word + '''s' 
    or w.word = w2.word + 'ing' 
    or w.word = w2.word + substring(w2.word, len(w2.word), 1) + 'ed'  
    or w.word = w2.word + substring(w2.word, len(w2.word), 1) + 'y' 
where len(w.word) >= 3 

die abgeleiteten Wörter zu löschen:

delete w from words w inner join words w2 
on w.word = w2.word + 's' 
    or w.word = w2.word + '''s' 
    or w.word = w2.word + 'ing' 
    or w.word = w2.word + substring(w2.word, len(w2.word), 1) + 'ed'  
    or w.word = w2.word + substring(w2.word, len(w2.word), 1) + 'y' 
where len(w2.word) >= 3 

die Anzahl der Wörter zu zählen, können Sie dies tun: Ich bin sicher, es ist ein eleganter Weg, dies zu tun, und wird aktualisiert diesen Beitrag, wenn ich einen finde. Fügen Sie zuerst eine Ansicht hinzu, oder erstellen Sie eine temporäre Tabelle #root_words und fügen Sie Folgendes ein, wenn Sie dies nicht können.

create view root_words as 
select distinct w2.word as root_word, w.word as derived_word 
from words w inner join words w2 
on w.word = w2.word + 's' 
    or w.word = w2.word + '''s' 
    or w.word = w2.word + 'ing' 
    or w.word = w2.word + substring(w2.word, len(w2.word), 1) + 'ed'  
    or w.word = w2.word + substring(w2.word, len(w2.word), 1) + 'y' 
where len(w2.word) >= 3 

Dann ist diese Abfrage funktioniert ein union auf Wörter wie „Hund“ enthalten, die nicht von einem anderen Wort abgeleitet. Andernfalls werden sie von der Zählung vermisst.

select x.root_word, count(*) 
from 
(
    select rw.root_word, rw.derived_word 
    from words w 
    inner join root_words rw on w.word = rw.root_word 
    -- add words which aren't derived from any other word 
    union all 
    select w.word as root_word, null as derived_word 
    from words w 
    left join root_words rw on w.word = rw.derived_word 
    where rw.root_word is null 
) x 
group by x.root_word 
+0

danke für Ihre Antwort löschen funktioniert sehr gut, aber wie kann ich die Partituren der Wörter vor dem Löschen zusammenfassen? –

Verwandte Themen