Laden...

Zeilen mit den meisten Treffern in Untertabelle zurückgeben

Erstellt von ravel vor 12 Jahren Letzter Beitrag vor 12 Jahren 1.932 Views
R
ravel Themenstarter:in
169 Beiträge seit 2007
vor 12 Jahren
Zeilen mit den meisten Treffern in Untertabelle zurückgeben

verwendetes Datenbanksystem: MSSQL Server 2008R2 Express

Hi,

ich habe zwei Tabellen maincontent und keywords. Keywords hat eine Fremdschlüsselbeziehung zu maincontent.

Hintergrund: Ich speichere Texte und dazu Keywords. Ich möchte nun anhand der eingegebenen Keywords ähnliche Texte zurückgeben lassen. Ähnlich = enthält so viele gleiche Keywords wie möglich.

Mein erster SQL-Versuch war folgender:


select top(5) * from maincontent left join keywords on maincontent.id = keywords.fk_keyword_id where keywords.id in (@keywords)

Das das nicht richtig funktioniert, habe ich selbst gemerkt. Da ja nicht die Trefferanzahl der Keywords berücksichtigt wird. Es wird nur geguckt, ob alle Keywords darin vorkommen.

Kann mir jemand bei dem SQL-Befehl auf die Sprünge helfen?

Vielen Dank!

48 Beiträge seit 2010
vor 12 Jahren

Du hast also eine Tabelle mit Keywords z.B.

{"Haus", "Küche", "Diele", "Bad", "Wohnzimmer", "Garten"}

und Texte wie z.B.:

{(1)"Ein Haus mit Küche und Bad",
(2)"Ein Haus mit Küche, Bad und Diele.",
(3)"Ein Haus mit Garten."}

Und Dein Result soll so aussehen:
(2)Count=4
(1)Count=3
(3)Count=2

Trifft es das in etwa?

R
ravel Themenstarter:in
169 Beiträge seit 2007
vor 12 Jahren

Vielleicht wird es so etwas klarer, wie mein Aufbau ist:
Im Frontend meiner Anwendung kann man einen Text eintippen (landet in der Tabelle maincontent) und zu dem Text keywords (landet in Tabelle keywords).
maincontent und keywords sind mit einer Fremdschlüsselbeziehung miteinandern verknüpft.

Ich möchte meinen Text außenvor lassen. Es geht mir nur um die Keywords.
Es sollen die 5 ähnlichsten Texte gefunden werden. Ähnlich heißt bei mir, es sollen so viele Keywords wie möglich übereinstimmen. Das ganze sortiert nach Anzahl der übereinstimmenden Keywords.

48 Beiträge seit 2010
vor 12 Jahren

Würde das so für Dich funktionieren?

SELECT Keywords.ContentID, Count(Keywords.ContentID) AS Vorkommen
FROM Keywords
GROUP BY Keywords.ContentID, Keywords.Keyword
HAVING (((Keywords.Keyword)='Haus'));
R
ravel Themenstarter:in
169 Beiträge seit 2007
vor 12 Jahren

Hi,

das Problem ist, dass ich als Parameter (@keywords) eine kommagetrennte Liste mit keywords übergeben möchte.

Dein Beispiel (und meines auch) funktioniert nur mit einem Keyword. Sobald ich "stichwort1,stichwort2" übergebe, wird nichts mehr zurückgegeben, obwohl die Keywords den Texten zugeordnet waren.


SELECT        TOP (5) maincontent.id, maincontent.approved, maincontent.title, maincontent.description, maincontent.text, maincontent.date_added, 
                         maincontent.fk_category_id
FROM            maincontent INNER JOIN
                         keywords ON maincontent.id = keywords.fk_maincontent_id
WHERE        (keywords.keyword IN (@keyword))

EDIT: Wenn es die Sache einfacher macht, würde ich auch auf die Untertabelle "keywords" verzichten und die Keywords kommagetrennt in einer Spalte von maincontent abspeichern. Ich glaube aber, dadruch wirds noch komplizierter.

Mein Vorhaben ist ja immer noch, die 5 "ähnlichsten" Texte zurückzuliefern.

48 Beiträge seit 2010
vor 12 Jahren

Wenn Du 3 Tabellen machst.

Keywords: ID|Keyword
Content: ID|Text
ContentKeywords: IDKeyword|IDContent

Kannst Du die Abfrage so gestalten:


SELECT Content.Text, Sum(SummevonID) AS SummevonSummevonID
FROM (SELECT Content.Text, Count(ContentKeywords.ID) AS SummevonID
FROM (Keywords INNER JOIN ContentKeywords ON Keywords.ID = ContentKeywords.KeywordID) INNER JOIN Content ON ContentKeywords.ContentID = Content.ID
GROUP BY Content.Text, Keywords.Keyword
HAVING (((Keywords.Keyword)='Haus' Or (Keywords.Keyword)='Boot' Or (Keywords.Keyword)='Auto')))
GROUP BY Content.Text;

Das mit dem Or und Top(5), bekommst Du selbst hin. ganz sicher 😃

R
ravel Themenstarter:in
169 Beiträge seit 2007
vor 12 Jahren

Hi,

erstmal vielen Dank für deine Hilfe! Ich würde aber ganz gerne ohne zusätzliche dritte Tabelle auskommen.

Ich hab jetzt selbst mal was gebastelt, was der Sache schon sehr nahe kommt. Leider bekomme ich bei dem Ausdruck immer noch einen Fehler.


  SELECT TOP (5) maincontent.id, maincontent.text
                        FROM maincontent INNER JOIN keywords ON maincontent.id = keywords.fk_maincontent_id
                        WHERE keyword in ('haus', 'auto', 'boot')
                        GROUP BY maincontent.id, maincontent.text
                        ORDER BY (select COUNT(keyword) as num, keyword from keywords
                        WHERE keyword in ('haus', 'auto', 'boot')
                        group by keyword
                        order by num desc);

Der Fehler lautet: > Fehlermeldung:

Die ORDER BY-Klausel ist in Sichten, Inlinefunktionen, abgeleiteten Tabellen, Unterabfragen und allgemeinen Tabellenausdrücken nur dann gültig, wenn auch TOP oder FROM XML angegeben wird.

Wenn ich das letzte order-by weglasse, kommt ein anderer Fehler:> Fehlermeldung:

Nur ein einziger Ausdruck kann in der Auswahlliste angegeben werden, wenn die Unterabfrage nicht mit EXISTS eingeleitet wird.

Ich bräuchte die Sache aber natürlich sortiert.