2008-09-19 13 views
9

Mam dwie tabele Organizacja i pracownik mający jedną lub wiele relacji, np. Jedna organizacja może mieć wielu pracowników. Teraz chcę wybrać wszystkie informacje dotyczące konkretnej organizacji oraz imię i nazwisko wszystkich pracowników tej organizacji. Jaki jest najlepszy sposób na zrobienie tego? Czy mogę uzyskać to wszystko w jednym zestawie rekordów lub będę musiał uzyskać wiele wierszy na podstawie nie. pracowników? Oto nieco graficzny wykazanie co chcę:Jak uzyskać wiele rekordów przeciwko jednemu rekordowi na podstawie relacji?

Org_ID  Org_Address Org_OtherDetails Employess 

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

Odpowiedz

0

Jeśli używasz Oracle można utworzyć PL/SQL funkcji można użyć w zapytaniu który akceptuje organization_id jako wejście i zwraca imię wszystkich pracownicy należący do tego org jako ciąg. Na przykład: -

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

Wszystko zależy. Jeśli wykonasz łączenie, otrzymasz wszystkie dane organizacji w każdym wierszu. (1 wiersz na pracownika). To kosztuje. Jeśli wykonasz dwa zapytania. (Org i Emp), który ma inny koszt.

Wybierz swoją truciznę.

2

w MS SQL można zrobić:

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 

wtedy zrobić:

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

myślę, że można to zrobić z COALESCE(), jak również, ale nie pamiętam składni OFF góra mojej głowy

+1

Oczywiście, jak tylko jako suma wszystkich swoich pracowników nazwisk, plus przecinki i przestrzenie osiągają 8000 - masz problem! – Valerion

0

Krótka odpowiedź brzmi "nie".

Jak zauważono w innych odpowiedziach, istnieją sposoby specyficzne dla dostawcy, aby osiągnąć ten wynik, ale nie ma czystego rozwiązania SQL, które działa w jednym zapytaniu. ?

przykro :(

Przypuszczalnie jednym z konkretnych rozwiązań sprzedawca będzie pracować dla Ciebie

0

Oto co można zrobić, masz 2 opcje:

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

ten sposób dostanie dodatkowe dane w każdym wierszu - pełne informacje o organizacji, których naprawdę nie potrzebujesz

Lub możesz zrobić:

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

Drugie podejście ma zastosowanie, jeśli chcesz zobaczyć, tj. lista nazw użytkowników "user1, user2, user3", ale nie chcesz działać na samych polach ...

3

Ponieważ pytanie jest oznaczone jako MySQL, powinieneś być w stanie użyć rozwiązania specyficznego dla MySQL, a mianowicie , GROUP_CONCAT. Na przykład:

select Org_ID, Org_Address, Org_OtherDetails, 
     GROUP_CONCAT(employees) as Employees 
from employees a, organization b 
where a.org_id=b.org_id 
group by b.org_id; 
18

Pierwotne pytanie dotyczyło konkretnej bazy danych, ale być może jest to dobre miejsce na bardziej ogólną odpowiedź. To częste pytanie. Pojęcie, które opisujesz, jest często określane jako "Grupowanie konkatenacji". Nie ma standardowego rozwiązania w SQL-92 lub SQL-99. Potrzebujesz więc rozwiązania specyficznego dla dostawcy.

  • MySQL - Prawdopodobnie najprostsze rozwiązanie. Użyj wbudowanej funkcji GROUP_CONCAT. W przykładzie chciałbyś coś takiego:
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: PostgreSQL 9.0 jest teraz równie proste, że string_agg (wyrażenie, separator) jest wbudowany. Tutaj jest z „przecinkami przestrzeni” pomiędzy elementami:
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 

przed PostgreSQL 9.0 pozwala definiować własne funkcje agregujące CREATE kruszywa. Nieco więcej pracy niż MySQL, ale o wiele bardziej elastyczna. Więcej szczegółów można znaleźć pod numerem other post. (Oczywiście PostgreSQL 9.0 i później mieć tę opcję, jak również.)

  • Oracle & MS SQL Server - Utwórz procedurę przechowywaną, która bierze org_id jako wejścia i wyjścia do złączonych nazwisk pracowników. Następnie użyj tej procedury przechowywanej w zapytaniu. Niektóre inne odpowiedzi tutaj zawierają pewne szczegóły dotyczące pisania procedur przechowywanych, takich jak te.
select 
    o.ID, o.Address, o.OtherDetails, 
    MY_CUSTOM_GROUP_CONCAT_PROCEDURE(o.ID) as Employees 
from 
    organization o 
  • Inne technologie DBMS - Zapisana trasa procedura jest najbardziej prawdopodobne. Być może inni mogą zaktualizować tę odpowiedź za pomocą odpowiedzi na więcej technologii.
0

Dla SQL Server SQLCLR agregaty w tym projekcie są zainspirowane próbką kodu MSDN, jednak działają znacznie lepiej i pozwalają na sortowanie (jako łańcuchy) i alternatywne ograniczniki w razie potrzeby. Oferują one prawie równoważną funkcjonalność do GROUP_CONCAT MySQL dla SQL Server.

Pełne porównanie zalet/wad kruszywa CLR oraz do sporządzania roztworu XML można znaleźć w dokumentacji:

http://groupconcat.codeplex.com

Powiązane problemy