2010-09-17 21 views
6

Używam bazy danych Sybase ASE.
Mam dwie tabele, które wyglądają jak:Zapytanie SQL o "concatenate on join"

tabeli Shops:

--------------------- 
| ShopName | ShopID | 
--------------------- 
| Sweetie | 1  | 
| Candie | 2  | 
| Sugarie | 3  | 
--------------------- 

Tabela Sweets:

---------------------- 
| SweetName | ShopID | 
---------------------- 
| lolly  | 1  | 
| redlolly | 1  | 
| greenloly | 1  | 
| taffy  | 2  | 
| redtaffy | 2  | 
| bluetaffy | 2  | 
| choco  | 3  | 
| mintchoco | 3  | 
| milkchoco | 3  | 
| gummybees | 3  | 
---------------------- 

Chcę napisać kwerendę, która będzie generować wynik, który wygląda tak:

----------------------------------------------------- 
| ShopName | Sweets         | 
----------------------------------------------------- 
| Sweetie | lolly, redlolly, greenlolly   | 
| Candie | taffy, redtaffy, bluetaffy    | 
| Sugarie | choco, mintchoco, milkchoco, gummybees | 
----------------------------------------------------- 

Jak mam to zrobić? Potrzebuję tego dla bazy danych Sybase ASE. Próbowałem funkcji LIST(), ale dostaję błąd w tym. Sprawdziłem jego dokumentację i okazało się, że ta funkcja nie jest dostępna w edycji ASE.

To prawdopodobnie oznacza, że ​​w grę wchodzi "dynamiczny sql" (nie mam pojęcia, co to oznacza). Czy ktoś może pomóc?

Mogę chcieć ShopId zamiast ShopName w tabeli wyników ... Nie wiem jeszcze na pewno. Myślę, że to nie będzie duża różnica. Także spóźnienie przecinków w kolumnie wyników Sweets nie stanowi problemu. Wszystko czego chcę, to separator bez odstępów.

+0

Hmm brzmi jak chcesz funkcję agregacji ciągów. Nie jestem pewien, które bazy danych, które to zrobić, ale widzę czasami zobaczyć funkcje zdefiniowane przez użytkownika dla tego (natuarlly, który waha się od jednego dmbs do innego). Jakiej bazy danych używasz? – FrustratedWithFormsDesigner

+1

Używam syabse. – jrharshath

+0

Jakie błędy miał "list()"? Nie mogę pomóc z problemami Sybase, ale ktoś inny może rozpoznać komunikat o błędzie. – FrustratedWithFormsDesigner

Odpowiedz

5

Będziesz musiał określić, jakiego DBMS używasz.

MySQL's GROUP CONCAT jest dokładnie tym, czego potrzebujesz.

SELECT ShopName, GROUP_CONCAT(SweetName SEPARATOR ", ") 
FROM Shops a 
JOIN Sweets b 
ON a.ShopID = b.ShopID 
GROUP BY ShopName 
+2

A Oracle ma 'wmsys.wm_concat', choć wydaje się być nieudokumentowane. Nigdy sam tego nie używałem, ale znalazłem to dość szybko. Inne rozwiązanie Oracle używające 'connect by': http://halisway.blogspot.com/2006/08/oracle-groupconcat-updated-again.html – FrustratedWithFormsDesigner

+0

Muszę to zrobić z sybase ASE, więc to nie będzie działać dla mnie. .. Sybase ma funkcję LIST(), która to robi, ale nie jest obecna w edycji ASE. – jrharshath

+0

moje google-fu ujawnia ten link (http://www.projectdmx.com/tsql/rowconcatenate.aspx). Czy możesz przekonwertować to na SQL, który będę potrzebował w moim przypadku? – jrharshath

1

Przetestowałem to na serwerze SQL, ale mam nadzieję, że będzie działać również na Sybase. Jeśli nie, może zbliży się do ciebie na tyle, aby go rozwiązać.

Jeśli utworzyć tę funkcję:

CREATE FUNCTION SweetsList(@shopID int) 
RETURNS varchar(500) 
AS 
BEGIN 

    DECLARE @list varchar(500) 

    SELECT @list = COALESCE(@list+', ','') + SweetName 
    FROM Sweets 
    WHERE ShopID = @shopID 

    RETURN @list 
END 

mogę wtedy wykonać to zapytanie i uzyskać pożądane wyniki:

SELECT ShopName, dbo.SweetsList(ShopID) AS Sweets 
FROM Shops 

Nadzieja to pomaga.

+0

Mam tutaj dokładnie ten sam problem. Dla mnie (Sybase ASE 15.0), który nie działa. Z jakiegoś powodu zwraca tylko ostatni wiersz. Czy to zależy od wersji? A może ustawienie? – Marnix

2

Jest to kwerenda krzyżowa i jest niemożliwe z Sybase ASE w jednym zapytaniu.

Można utworzyć procedurę składowaną z tabelą tymczasową, wypełnić ją kursorem i wybrać z tej tabeli tymczasowej.

1

Niestety, metoda w odpowiedzi adrift's nie działa z instrukcją select dla Sybase ASE, zmienna @ lista nie aktualizuje się dla każdego wiersza, działa tylko dla ostatniego wiersza. Ale ponieważ aktualizacja działa dla każdego wiersza, a rozmiar tabeli nie jest duży, można to zrobić za pomocą instrukcji aktualizacji. Mały przykład:

declare @list varchar(500) 

    update Sweets 
    set @list = @list + SweetName + ', ' 
    where ShopID = 1 

    select SUBSTRING(@list, 1, Len(@list) - 2) 

P.S. Jak dla mnie, kursor nie jest dobrym sposobem ...

0

Pracuje w Sybase ASE ...

CREATE FUNCTION SweetsList(@SN varchar(10)) 
returns varchar(255) 
AS 
DECLARE @SwNList varchar(255) 
DECLARE @FetchSwN varchar(55) 
DECLARE @Status INT, @Error INT 

DECLARE ListCurs CURSOR FOR 
SELECT SweetName 
    FROM Sweets AS SW 
JOIN Shops AS SH 
    ON SH.ShopID = SW.ShopID 
WHERE SH.ShopName = @SN 
FOR READ ONLY 

OPEN ListCurs 
SELECT @Status = 0 
WHILE @Status = 0 
BEGIN 
    FETCH ListCurs INTO @FetchSwN 

    SELECT @Status = @@SQLSTATUS 

    IF @Status = 0 
    BEGIN 
     SELECT @SwNList = CASE WHEN @SwNList IS NULL THEN '' ELSE @SwNList + ', ' END + @FetchSwN 
    END 
END 
CLOSE ListCurs 
RETURN (@SwNList) 
go 

Następnie wykonywać ...

SELECT ShopName, dbo.SweetsList(ShopName) AS Sweets FROM Shops