Frage

Zusätzlich zu dieser Frage SQL-Abfrage gibt, die unterschiedliche Ergebnisse, die mehrere Spalten übereinstimmen das hatte eine sehr saubere Lösung, ich frage mich, wie der nächste Schritt aussehen:

 DOCUMENT_ID |     TAG
----------------------------
   1        |   tag1
   1        |   tag2
   1        |   tag3
   2        |   tag2
   3        |   tag1
   3        |   tag2
   4        |   tag1
   5        |   tag3

Also, um alle document_ids, die Tag haben 1 und 2 haben wir eine Abfrage wie folgt durchführen würde:

SELECT document_id
FROM table
WHERE tag = 'tag1' OR tag = 'tag2'
GROUP BY document_id
HAVING COUNT(DISTINCT tag) = 2

Nun wäre interessant zu wissen, was ist, wie wir alle verschieden document_ids bekommen würden, die Tags 1 und 2, und zusätzlich zu, dass die IDs haben, den Tag 3 hat. Wir könnten uns vorstellen die gleiche Abfrage machen und eine Verbindung zwischen ihnen ausführen:

SELECT document_id
FROM table
WHERE tag = "tag1" OR tag = "tag2"
GROUP BY document_id
HAVING COUNT(DISTINCT tag) = 2
UNION
SELECT document_id
FROM table
WHERE tag = "tag3"
GROUP BY document_id

Aber ich frage mich, ob mit der Bedingung hinzugefügt, wir von anderen Erstabfrage denken konnte. Ich stelle mir vor vielen „Gewerkschaften“, die wie das mit verschiedenen Tags und Tag zählt. Wäre es nicht sehr schlecht in Bezug auf den Leistungsketten von Gewerkschaften wie das zu schaffen?

War es hilfreich?

Lösung

Diese nutzt noch die Gewerkschaften der Art, kann aber leichter zu lesen und Kontrolle. Ich bin auf die Geschwindigkeit dieser Abfrage auf einem großen Datensatz wirklich interessiert, so lassen Sie es mich wissen, wie schnell es ist. Wenn ich in deinen kleinen Daten setzte eingestellt es dauerte 0,0001 Sekunden.

SELECT DISTINCT (dt1.document_id)
FROM 
  document_tag dt1,
  (SELECT document_id
    FROM document_tag
    WHERE tag =  'tag1'
  ) AS t1s,
  (SELECT document_id
    FROM document_tag
    WHERE tag =  'tag2'
  ) AS t2s,
  (SELECT document_id
    FROM document_tag
    WHERE tag =  'tag3'
  ) AS t3s
WHERE
  (dt1.document_id = t1s.document_id
  AND dt1.document_id = t2s.document_id
  )
  OR dt1.document_id = t3s.document_id

Das macht es einfach, neue Parameter hinzugefügt werden, da Sie bereits das Ergebnis für jeden Tag-Satz angegeben haben.

Zum Beispiel fügt hinzu:

OR dt1.document_id = t2s.document_id

bis zum Ende auch abholen document_id 2

Andere Tipps

Es ist möglich, dies innerhalb eines einzigen zu tun, aber Sie werden Ihre WHERE-Klausel in die having-Klausel, um fördern müssen, um eine disjunktive zu verwenden.

Sie sind richtig, wird diese bekommen langsamer und langsamer, wenn Sie neue Tags hinzufügen, die Sie für Klauseln in zusätzliche UNION zu suchen. Jede UNION-Klausel ist eine zusätzliche Abfrage, die geplant und ausgeführt werden muss. Und Sie werden nicht in der Lage zu sortieren, wenn Sie fertig sind.

Sie suchen nach einer grundlegenden Data-Warehousing-Technik. Zuerst lassen Sie mich Ihr Schema mit einer zusätzlichen Tabelle neu zu erstellen.

create table a (document_id int, tag varchar(10));

insert into a values (1, 'tag1'), (1, 'tag2'), (1, 'tag3'), (2, 'tag2'), 
                     (3, 'tag1'), (3, 'tag2'), (4, 'tag1'), (5, 'tag3');

create table b (tag_group_id int, tag varchar(10));

insert into b values (1, 'tag1'), (1, 'tag2'), (2, 'tag3');

Tabelle b enthält "Tag-Gruppen". Gruppe 1 umfasst tag1 und tag2, während Gruppe 2 enthält TAG3.

Jetzt können Sie Tabelle b Ändern Sie die Abfrage, die Sie interessiert sind zu repräsentieren Wenn Sie bereit abzufragen sind, erstellen Sie temporäre Tabellen aggregierten Daten zu speichern.

create temporary table c 
(tag_group_id int, count_tags_in_group int, tags_in_group varchar(255));

insert into c
select 
    tag_group_id,
    count(tag),
    group_concat(tag)
from b
group by tag_group_id;

create temporary table d (document_id int, tag_group_id int, document_tag_count int);

insert into d
select
    a.document_id,
    b.tag_group_id,
    count(a.tag) as document_tag_count
from a
inner join b on a.tag = b.tag
group by a.document_id, b.tag_group_id;

c enthält die Anzahl der Tags für Tag-Gruppe und d enthält die Anzahl der Tags jedes Dokument für jeden Tag Gruppe hat. Wenn eine Zeile in c eine Zeile in d übereinstimmt, dann das bedeutet, dass Dokument alle Tags in dieser Variablengruppe hat.

select 
    d.document_id as "Document ID",
    c.tags_in_group as "Matched Tag Group"
from d
inner join c on d.tag_group_id = c.tag_group_id
            and d.document_tag_count = c.count_tags_in_group

Eine coole Sache an diesem Ansatz ist, dass Sie Berichte wie ‚Wie viele Dokumente haben 50% oder mehr der Tags in jedem dieser Variablengruppen?‘ Laufen könnten

select 
    d.document_id as "Document ID",
    c.tags_in_group as "Matched Tag Group"
from d
inner join c on d.tag_group_id = c.tag_group_id
            and d.document_tag_count >= 0.5 * c.count_tags_in_group
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top