Frage

Ich habe drei Tabellen tag, page, pagetag

Mit den Daten unter

Seite

ID      NAME
1       page 1
2       page 2
3       page 3
4       page 4

Tags

ID      NAME
1       tag 1
2       tag 2
3       tag 3
4       tag 4

pagetag

ID   PAGEID  TAGID
1    2        1
2    2        3
3    3        4
4    1        1
5    1        2
6    1        3

Ich möchte gerne einen string mit dem Korrespondent der-tag-Namen für jede Seite, die mit SQL in einer einzigen Abfrage.Dies ist meine gewünschte Ausgabe.

ID      NAME       TAGS
1       page 1     tag 1, tag 2, tag 3
2       page 2     tag 1, tag 3
3       page 3     tag 4
4       page 4    

Ist dies möglich mit SQL?


Ich bin mit MySQL.Nichtsdestoweniger ich möchte eine Datenbank-Hersteller unabhängige Lösung, wenn möglich.

War es hilfreich?

Lösung

Sergio del Amo:

Jedoch, ich bin nicht immer der Seiten ohne tags.Ich glaube, ich muss schreiben, meine Abfrage mit left outer joins.

SELECT pagetag.id, page.name, group_concat(tag.name)
FROM
(
    page LEFT JOIN pagetag ON page.id = pagetag.pageid
)
LEFT JOIN tag ON pagetag.tagid = tag.id
GROUP BY page.id;

Nicht eine sehr hübsche Abfrage, aber sollte Ihnen das geben, was Sie wollen - pagetag.id und group_concat(tag.name) werden null Seite 4 in dem Beispiel, das Sie oben gepostet habe, aber die Seite wird in den Ergebnissen angezeigt.

Andere Tipps

Ja, Sie können tun es über die 3 etwas wie die unten:

SELECT page_tag.id, page.name, group_concat(tags.name)
FROM tag, page, page_tag
WHERE page_tag.page_id = page.page_id AND page_tag.tag_id = tag.id;

Hat nicht getestet worden und könnte wohl geschrieben werden, ein bisschen effizienter, aber das sollte Ihnen den Einstieg!

Auch MySQL ist angenommen, so kann nicht spielen so schön mit MSSQL!Und MySQL ist nicht wild über Bindestriche in das Feld Namen, so verändert Unterstriche in den obigen Beispielen.

So weit ich bin mir bewusst, SQL92 nicht definieren, wie die string-Verkettung getan werden sollte.Dies bedeutet, dass die meisten Motoren haben Ihre eigene Methode.

Wenn Sie möchten, dass eine Datenbank-unabhängige Methode, Sie ' ll haben zu tun es außerhalb der Datenbank.

(ungetestet in allen, aber Oracle)

Oracle

SELECT field1 | ', ' | field2
FROM table;

MS SQL

SELECT field1 + ', ' + field2
FROM table;

MySQL

SELECT concat(field1,', ',field2)
FROM table;

PostgeSQL

SELECT field1 || ', ' || field2
FROM table;

Ich habe eine Lösung spielen mit joins.Die Abfrage ist:

SELECT
    page.id AS id,
    page.name AS name,
    tagstable.tags AS tags
FROM page 
LEFT OUTER JOIN 
(
    SELECT pagetag.pageid, GROUP_CONCAT(distinct tag.name) AS tags
    FROM tag INNER JOIN pagetag ON tagid = tag.id
    GROUP BY pagetag.pageid
)
AS tagstable ON tagstable.pageid = page.id
GROUP BY page.id

Und zu dieser Ausgabe:

id   name    tags
---------------------------
1    page 1  tag2,tag3,tag1
2    page 2  tag1,tag3
3    page 3  tag4
4    page 4  NULL

Ist es möglich, steigern Sie die Geschwindigkeit von Abfragen schreiben es einen anderen Weg?

pagetag.id und group_concat(Tags.name) wird null für die Seite 4 im Beispiel oben gepostet habe, aber die Seite wird in den Ergebnissen angezeigt.

Sie verwenden können die COALESCE Funktion zum entfernen der Nullen, wenn Sie benötigen:

select COALESCE(pagetag.id, '') AS id ...

Es wird wieder das erste nicht-null-Wert aus der Liste der Parameter.

Ich glaube, Sie kann verwenden müssen, um mehrere updates.

So etwas wie (nicht getestet):

select ID as 'PageId', Name as 'PageName', null as 'Tags'
into #temp 
from [PageTable]

declare @lastOp int
set @lastOp = 1

while @lastOp > 0
begin
    update p
    set p.tags = isnull(tags + ', ', '' ) + t.[Tagid]
    from #temp p
        inner join [TagTable] t
            on p.[PageId] = t.[PageId]
    where p.tags not like '%' + t.[Tagid] + '%'

    set  @lastOp == @@rowcount
end

select * from #temp

Hässlich, aber.

Das Beispiel T-SQL, aber ich denke, MySql hat-äquivalente für alles verwendet.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top