Данные SQL возвращаются в списке через запятую - PullRequest
2 голосов
/ 21 декабря 2010

Вот мои таблицы:

-----------------------------------------
Hotels
-----------------------------------------
HotelID | HotelName
-----------------------------------------


-----------------------------------------
HotelImages
-----------------------------------------
HotelImageID | HotelID | Filename
-----------------------------------------

Я хотел бы создать инструкцию SELECT, которая будет возвращать данные следующим образом:

HotelID | HotelName | Images
-----------------------------------------
1 | Hotel1 | Image1,Image2,Image3
2 | Hotel2 | Image4,Image5,Image6

Как я могу изменить свой запрос насделай это?У меня есть:

SELECT H.HotelID, H.HotelName, '' AS Images
FROM Hotels H

Я знаю, что могу использовать COALESCE для создания списка, разделенного запятыми:

DECLARE @Images varchar(500)
SELECT @Images = COALESCE(@Images + ',', '') + CAST(Filename AS varchar(100)) FROM HotelImages WHERE HotelID = 1
SELECT @Images

Но я не знаю, как интегрировать это в мой текущий запрос, такчто список может быть возвращен вместе с остальными данными отеля.

Я должен упомянуть, что я использую SQL Server 2000.

Ответы [ 3 ]

2 голосов
/ 21 декабря 2010

Поскольку это SQL 2000, ваши возможности несколько ограничены.Вы не можете использовать FOR XML PATH или рекурсивные CTE

. Трюк COALESCE работает только для заполнения списка с разделителями-запятыми для одного отеля.Не все из них.

Честно говоря, вам лучше сделать это на клиенте.Но если этого нельзя сделать (приходят на ум определенные приложения для отчетов, имена которых не должны быть названы), вы можете сделать следующее.

Обратите внимание, сколько раз процесс цикла равен максимальному количеству файлов, связанных с отелем.Это намного лучше, чем настройка цикла для каждого отеля (например, вызов UDF из предложения select).

DECLARE @foo table ( HotelID int , lastID int , FileNameList varchar(8000))

INSERT INTO @Foo 

SELECT
    start.HotelID,
    start.firstID ,
    id.FileName 

FROM
    (SELECT 
        HotelID,
        min(HotelImageID ) firstID
    from 
        HotelImages


    group by HotelID) start
    INNER JOIN HotelImages hi
    ON start.firstID = hi.HotelImageID 


WHILE @@RowCount <> 0 
BEGIN

    UPDATE @foo
    SET 
        FileNameList = FileNameList + ',' + FileName
        lastID  = Xnext.nextID
    FROM 
        @foo f
        INNER JOIN HotelImages hi
        ON f.HotelID = id.HotelID
        INNER JOIN 
        (SELECT 

            id.HotelID,
            min(HotelImageID ) nextID
        from HotelImages hi
              inner join @foo f
              on f.HotelID = id.HotelID
        where id.HotelImageID  > f.lastid


        group by id.HotelID) Xnext

        ON Xnext.nextID = id.HotelImageID 



END 

SELECT 
    h.HotelID 
    h.HotelName,
    f.FileNameList
FROM
    Hotels h
    INNER JOIN @foo f
    ON h.hotelId = f.HotelId
1 голос
/ 21 декабря 2010

попробуйте это:

SELECT H.HotelID, H.HotelName, 
Images = (select COALESCE(HotelImageID + ',', '') 
            FROM HotelImages 
            WHERE HotelID = H.id)
FROM Hotels H
0 голосов
/ 21 декабря 2010

COALESCE не делает то, что вы предлагаете.Возвращает первое ненулевое значение из списка.Он не агрегирует значения по строкам.(Хотя я согласен с тем, что он звучит так же, как и при агрегации).

SQL Server не имеет прямой поддержки агрегации с конкатенацией строк (например, в MySQL есть GROUP_CONCAT).Я видел несколько опубликованных решений, которые предоставляют такую ​​функциональность, но я уверен, что они предназначены для SQL-2005 и выше.Google (или поиск здесь) на "GROUP_CONCAT FOR SQL SERVER".

...