Динамический многостолбцовый SQL - PullRequest
2 голосов
/ 30 сентября 2011

У меня есть две таблицы с такими структурами:

VelocityBase

Проход | ItemId | ConfigId | InventSizeId | InventColorId | InventLocationId | DataAreaId | VelocityCategory

VelocitySalesCount

ItemId | ConfigId | InventSizeId | InventColorId | InventLocationId | DataAreaId | Продажи

Каждая строка в Базовой таблице представляет SKU, а сумма полей «Sales» связанных записей SalesCount определяет «Picks». Этот запрос работает:

SELECT Aisle, COUNT(*) as '# SKUs', 
SUM(Sales) as '# Picks', 
SUM(CASE WHEN VelocityCategory = 'Hot' THEN 1 ELSE 0 END) as 'Hot SKUs', 
SUM(CASE WHEN VelocityCategory = 'Hot' THEN SALES ELSE 0 END) as 'Hot Picks', 
SUM(CASE WHEN VelocityCategory = 'Warm' THEN 1 ELSE 0 END) as 'Warm SKUs', 
SUM(CASE WHEN VelocityCategory = 'Warm' THEN SALES ELSE 0 END) as 'Warm Picks', 
SUM(CASE WHEN VelocityCategory = 'Cold' THEN 1 ELSE 0 END) as 'Cold SKUs', 
SUM(CASE WHEN VelocityCategory = 'Cold' THEN SALES ELSE 0 END) as 'Cold Picks'
FROM [dbo].[VelocityBase] Base
LEFT OUTER JOIN [dbo].[VelocitySalesCount] SalesCount
ON Base.ItemId = SalesCount.ItemId 
AND Base.ConfigId = SalesCount.ConfigId 
AND Base.InventSizeId = SalesCount.InventSizeId 
AND Base.InventColorId = SalesCount.InventColorId 
AND Base.InventLocationId = SalesCount.InventLocationId 
AND SalesCount.DataAreaId = Base.DataAreaId
GROUP BY Aisle
ORDER BY Aisle

Однако столбцы жестко запрограммированы. Я хотел бы, чтобы «горячие», «теплые», «холодные» и т. Д. Генерировались на основе значений, которые присутствуют в базе данных для этого столбца. Таким образом, если пользователь добавит строку с «Lukewarm» в качестве VelocityCategory, с этими данными появятся два новых столбца.

Я не уверен, что что-то вроде SQL для генерации SQL или, возможно, функция PIVOT сработает.

Заранее спасибо!

EDIT:

Я сужаюсь. У меня есть сумма сумм продаж, используя это:

DECLARE @SQLStatement NVARCHAR(4000)
        ,@PivotValues NVARCHAR(4000);
SET @PivotValues = '';

SELECT  @PivotValues = @PivotValues + ',' + QUOTENAME(VelocityCategory)
FROM
(
        SELECT DISTINCT VelocityCategory
        FROM dbo.VelocityBase
) src;
SET @PivotValues = SUBSTRING(@PivotValues,2,4000);

SELECT  @SQLStatement = 
'SELECT pvt.*
FROM
(
SELECT Aisle, VelocityCategory, Sales
FROM VelocityBase Base
LEFT OUTER JOIN [dbo].[VelocitySalesCount] SalesCount
ON Base.ItemId = SalesCount.ItemId 
AND Base.ConfigId = SalesCount.ConfigId 
AND Base.InventSizeId = SalesCount.InventSizeId 
AND Base.InventColorId = SalesCount.InventColorId 
AND Base.InventLocationId = SalesCount.InventLocationId 
AND SalesCount.DataAreaId = Base.DataAreaId
) VelocityBase
PIVOT ( Sum(Sales) FOR VelocityCategory IN ('+@PivotValues+') ) pvt';

EXECUTE sp_executesql @SQLStatement; 

Спасибо за ссылку на предыдущий вопрос, который дошел до меня.

Ответы [ 2 ]

1 голос
/ 03 октября 2011

Я обычно не использую PIVOT, просто "обычный" динамический SQL, например:

     DECLARE @sSQL NVARCHAR(MAX)= '' ,
            @sSQLSum NVARCHAR(MAX)= '' ,
            @sSQlBegin NVARCHAR(MAX)= '
               SELECT Aisle, COUNT(*) As ''# SKUs'', 
                SUM(Sales) As ''# Picks'', 
                ' ,
            @sSQLEnd NVARCHAR(MAX)= 'FROM [Dbo].[VelocityBase] Base
        LEFT OUTER JOIN [Dbo].[VelocitySalesCount] SalesCount
        ON Base.ItemId = SalesCount.ItemId 
        AND Base.ConfigId = SalesCount.ConfigId 
        AND Base.InventSizeId = SalesCount.InventSizeId 
        AND Base.InventColorId = SalesCount.InventColorId 
        AND Base.InventLocationId = SalesCount.InventLocationId 
        AND SalesCount.DataAreaId = Base.DataAreaId
        GROUP BY Aisle
        ORDER BY Aisle' ;

        WITH    c AS ( SELECT DISTINCT
                                VelocityCategory N
                       FROM     Dbo.VelocityBase
                     )
            SELECT  @sSQLSum = @sSQLSum + 'SUM(CASE WHEN c.N=''' + c.N
                    + ''' THEN 1 ELSE 0 END ) AS ''' + c.N + ' SKUs'',' + CHAR(13)
                    + 'SUM(CASE WHEN c.N=''' + c.N
                    + ''' THEN SALES ELSE 0 END ) AS ''' + c.N + ' Sales'',' + CHAR(13)
            FROM    c
IF(LEN(@sSQLSum))>0        
SET @sSQLSum = LEFT(@sSQLSum, ( LEN(@sSQLsum) - 2 )) 

    SET @sSQL = @sSQlBegin + @sSQLSum + CHAR(13) + @sSQLEnd

    EXEC (@sSQL)
0 голосов
/ 30 сентября 2011

Если вы не генерируете запрос динамически, я не думаю, что есть способ создать то, что вы хотите.

Ваша проблема может быть легко решена, если ваши таблицы были нормализованы.Например, таблица VelocityBase должна иметь столбец VelocityCategoryID вместо столбца VelocityCategory.Этот новый столбец должен быть foreign key для новой таблицы с именем VelocityCategory (или что-то в этом роде), тогда ваш запрос для этого вычисления становится почти тривиальным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...