Группировать по результатам коррелированного подзапроса в SQL 2005 - PullRequest
3 голосов
/ 17 ноября 2010

Я впервые пишу о переполнении стека, но уже нашел, что это бесценный ресурс.

Мой вопрос связан с коррелированными подзапросами в группе оператора SQL, что, как я понимаю, невозможно. Я надеюсь, что, объяснив цель запроса, я смогу найти некоторую помощь. В своей простейшей форме я пытаюсь агрегировать по первичному ключу и группе по результатам коррелированного подзапроса. Поле, используемое для корреляции, является уникальным для каждой записи первичного ключа. Если я группирую по полю корреляции, это не дает ожидаемых результатов. Мне нужно иметь возможность группировать по результатам коррелированного подзапроса, но я не уверен, как реструктурировать запрос. Пример запроса приведен ниже.

Спасибо

-John

SELECT DISTINCT 
    (SELECT substring(CommaDelimitedTranslatedList, 0, len(CommaDelimitedTranslatedList)) 
    FROM 
        ( 
            SELECT 
                cd.choiceValue + ',' 
            from SelectedChoiceTable sct 
                join ChoiceDescription cd on 
                    cd.ChoiceID = sct.ChoiceID 
            where 
                sct.ChoiceSet = TargetJoinTable.ChoiceKey  FOR XML PATH('')
        ) D ( CommaDelimitedTranslatedList ))  AS           [TargetJoinTableCommaDelimitedTranslatedList1] ,
    count(BaseTable.BaseKey)
 FROM BaseTable
    join TargetJoinTable on 
        BaseTable.BaseKey = TargetJoinTable.BaseKey
Group By 
    [TargetJoinTableCommaDelimitedTranslatedList1]
Order By 
    [TargetJoinTableCommaDelimitedTranslatedList1] ASC

1 Ответ

2 голосов
/ 17 ноября 2010

На первый взгляд попробуйте изменить подзапрос на CROSS (или OUTER) APPLY. Это перемещает «столбец» в предложение FROM из предложения SELECT, что позволяет группировать.

SELECT
    foo.TargetJoinTableCommaDelimitedTranslatedList1 ,
    count(BaseTable.BaseKey)
 FROM
    BaseTable
    join
    TargetJoinTable on BaseTable.BaseKey = TargetJoinTable.BaseKey
    CROSS APPLY
    (
    SELECT
        substring(CommaDelimitedTranslatedList, 0, 2000000000)
               AS TargetJoinTableCommaDelimitedTranslatedList1
    FROM 
        ( 
        SELECT 
            cd.choiceValue + ',' 
        from
            SelectedChoiceTable sct 
            join
            ChoiceDescription cd on cd.ChoiceID = sct.ChoiceID 
        where 
            sct.ChoiceSet = TargetJoinTable.ChoiceKey
        FOR XML PATH('')
        ) D ( CommaDelimitedTranslatedList )
      ) foo
Group By 
    foo.TargetJoinTableCommaDelimitedTranslatedList1
Order By 
    foo.TargetJoinTableCommaDelimitedTranslatedList1 ASC

Или переместите агрегат на производную таблицу, таким образом

SELECT
    COUNT(foo.BaseKey),
    TargetJoinTableCommaDelimitedTranslatedList1
FROM
    (SELECT DISTINCT 
        (SELECT substring(CommaDelimitedTranslatedList, 0, len(CommaDelimitedTranslatedList)) 
        FROM 
            ( 
                SELECT 
                    cd.choiceValue + ',' 
                from SelectedChoiceTable sct 
                    join ChoiceDescription cd on 
                        cd.ChoiceID = sct.ChoiceID 
                where 
                    sct.ChoiceSet = TargetJoinTable.ChoiceKey  FOR XML PATH('')
            ) D ( CommaDelimitedTranslatedList ))  AS           [TargetJoinTableCommaDelimitedTranslatedList1] ,
     BaseTable.BaseKey

     FROM BaseTable
        join TargetJoinTable on 
            BaseTable.BaseKey = TargetJoinTable.BaseKey
    ) foo
Group By 
    [TargetJoinTableCommaDelimitedTranslatedList1]
Order By 
    [TargetJoinTableCommaDelimitedTranslatedList1] ASC

Одна проблема с этим будет в том, что CSV TargetJoinTableCommaDelimitedTranslatedList1 может быть сгенерирован много раз: один раз для BaseTable.BaseKey, если я правильно прочитал. Который будет медленным. Я чувствую, что поколение CSV должно быть последним: на самом деле вы группируете по TargetJoinTable.ChoiceKey, а не по CSV, которое оно генерирует.

...