2008-09-19 4 views
9

Ich habe zwei Tabellen Organisation und Mitarbeiter haben einen zu vielen Beziehungen, d. H. Eine Organisation kann mehrere Mitarbeiter haben. Jetzt möchte ich alle Informationen einer bestimmten Organisation sowie den Vornamen aller Mitarbeiter für diese Organisation auswählen. Was ist der beste Weg, es zu tun? Kann ich das alles in einem einzigen Datensatz bekommen, oder muss ich mehrere Zeilen basierend auf Nein bekommen. der Angestellten? Hier ist ein bisschen grafische Demonstration dessen, was ich will:Wie erhält man mehrere Datensätze für einen Datensatz basierend auf Relation?

Org_ID  Org_Address Org_OtherDetails Employess 

1   132A B Road List of details  Emp1, Emp2, Emp3..... 

Antwort

0

Wenn Sie Oracle verwenden, können Sie eine PL/SQL-Funktion erstellen Sie in Ihrer Abfrage verwenden können, die eine organization_id als Eingabe akzeptiert und gibt den ersten Namen aller Mitarbeiter, die zu dieser Organisation gehören, als Zeichenfolge. Zum Beispiel: -

select 
    o.org_id, 
    o.org_address, 
    o.org_otherdetails, 
    org_employees(o.org_id) as org_employees 
from 
    organization o 
0

Es hängt alles ab. Wenn Sie einen Join durchführen, erhalten Sie alle Organisationsdaten in jeder Zeile. (1 Zeile pro Mitarbeiter). Das hat Kosten. Wenn Sie zwei Abfragen ausführen. (Org und Emp), das hat andere Kosten.

Wählen Sie Ihr Gift aus.

2

in MS SQL können Sie tun:

create function dbo.table2list (@input int) 
returns varchar(8000) 
as 
BEGIN 
declare @putout varchar(8000) 
set @putout = '' 
select @putout = @putout + ', ' + <employeename> 
from <employeetable> 
where <orgid> = @input 
return @putout 
end 

dann tun:

select * from org, dbo.table2list(orgid) 
from <organisationtable> 

Ich glaube, Sie es mit COALESCE tun können() als gut, aber die Syntax aus der nicht mehr erinnern kann Spitze meines Kopfes

+1

Natürlich, sobald die Summe aller Ihrer Mitarbeiter Namen, Plus Kommas und Leerzeichen erreichen 8000 - Sie haben ein Problem! – Valerion

0

Die kurze Antwort ist "Nein".

Wie in anderen Antworten erwähnt, gibt es herstellerspezifische Möglichkeiten, um dieses Ergebnis zu erreichen, aber es gibt keine reine SQL-Lösung, die in einer Abfrage funktioniert. ?

traurig über das :(

Vermutlich eine der herstellerspezifischen Lösungen für Sie arbeiten

0

Hier ist, was Sie tun können, haben Sie 2 Möglichkeiten:

select * 
FROM 
    users u 
    LEFT JOIN organizations o ON (u.idorg = o.id); 

Auf diese Weise können erhalten zusätzliche Daten für jede Zeile - vollständige Organisation Informationen, die Sie nicht wirklich benötigen.

Oder Sie können tun:

select o.*, group_concat(u.name) 
FROM 
    users u 
    LEFT JOIN organizations o ON (u.idorg = o.id) 
GROUP BY 
    o.id 

http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat

Der zweite Ansatz ist anwendbar, wenn Sie also sehen wollen. Liste der Benutzernamen "user1, user2, user3", aber nicht auf den Feldern selbst arbeiten wollen ...

3

Da die Frage als MySQL getaggt ist, sollten Sie in der Lage sein, eine MySQL-spezifische Lösung zu verwenden, nämlich , GROUP_CONCAT. Zum Beispiel

18

Die ursprüngliche Frage war datenbankspezifisch, aber vielleicht ist dies ein guter Ort, um eine allgemeinere Antwort aufzunehmen. Es ist eine häufige Frage. Das Konzept, das Sie beschreiben, wird oft als "Gruppenkonkatenation" bezeichnet. Es gibt keine Standardlösung in SQL-92 oder SQL-99. Sie benötigen also eine herstellerspezifische Lösung.

  • MySQL - Wahrscheinlich die einfachste Lösung. Verwenden Sie die integrierte GROUP_CONCAT-Funktion. In Ihrem Beispiel würden Sie so etwas wie dies wollen:
  • select 
        o.ID, o.Address, o.OtherDetails, 
        GROUP_CONCAT(concat(e.firstname, ' ', e.lastname)) as Employees 
    from 
        employees e 
        inner join organization o on o.org_id=e.org_id 
    group by o.org_id 
    
    • PostgreSQL - EDIT: 9.0 PostgreSQL ist ebenso einfach jetzt, dass string_agg (Ausdruck, Trennzeichen) ist eingebaut. Hier ist es mit ‚Komma-Raum‘ zwischen den Elementen:
    select 
        o.ID, o.Address, o.OtherDetails, 
        STRING_AGG((e.firstname || ' ' || e.lastname), ', ') as Employees 
    from 
        employees e 
        inner join organization o on o.org_id=e.org_id 
    group by o.org_id 
    

    PostgreSQL vor 9.0 können Sie Ihre eigenen Aggregatfunktionen definieren, mit AGGREGATEN CREATE. Etwas mehr Arbeit als MySQL, aber viel flexibler. Siehe hierzu other post für weitere Details. (Natürlich PostgreSQL 9.0 und später über diese Option auch.)

    • Oracle & MS SQL Server - Erstellen Sie eine gespeicherte Prozedur, die die Org_ID als seine Eingabe nimmt und gibt die verketteten Mitarbeiternamen. Verwenden Sie dann diese gespeicherte Prozedur in Ihrer Abfrage. Einige der anderen Antworten hier enthalten einige Details darüber, wie gespeicherte Prozeduren wie diese geschrieben werden.
    select 
        o.ID, o.Address, o.OtherDetails, 
        MY_CUSTOM_GROUP_CONCAT_PROCEDURE(o.ID) as Employees 
    from 
        organization o 
    
    • Andere DBMS-Technologien - Die gespeicherte Prozedur Route am wahrscheinlichsten ist. Vielleicht können andere diese Antwort mit mehr technologiespezifischen Antworten aktualisieren.
    0

    Für SQL Server SQLCLR aggregieren Aggregate in diesem Projekt von dem MSDN-Codebeispiel, jedoch führen sie viel besser aus und ermöglichen das Sortieren (als Zeichenfolgen) und alternative Trennzeichen bei Bedarf. Sie bieten fast äquivalente Funktionalität zu MySQL GROUP_CONCAT für SQL Server.

    Ein vollständiger Vergleich der Vor-/Nachteile der CLR-Aggregate und die FOR XML-Lösung finden Sie in der Dokumentation:

    http://groupconcat.codeplex.com

    Verwandte Themen