2012-02-14 5 views
0
-- Pivot table with one row and four columns 

SELECT 'Values' tValues, 
    ID,Name,ValueID,Value FROM (

     Select ID,Name,ValueID,Value FROM Table WHERE OptionID = 1000000 

    ) AS SourceTable 

    PIVOT ( 

     COUNT(tValues) 
     FOR tValues IN (ID,Attribute,ValueID,Value) 

    ) AS PivotTable; 

Я поднятием пример на сайте Microsoft.com: http://msdn.microsoft.com/en-us/library/ms177410.aspxСводная таблица с одной строкой и четырьмя столбцами

Но есть несколько вещей, о Pivot я действительно не понимаю, так что не быть удивленным, когда вы видите его в приведенном выше коде, например COUNT(tValues), я понятия не имею, для чего это нужно, судя по примеру на microsoft, кажется, что это всегда какое-то числовое значение, поэтому я решил, что попробую это, чтобы увидеть, вернет ли он что-то, но все, что он возвращает, является ошибкой. В любом случае, если кто-то может поделиться тем, почему этот запрос не работает, и, возможно, объяснить, для чего используется числовое значение выше FOR?

Table containts рентгеновский количество строк, с четырьмя колоннами, так это выглядит следующим образом:

ID | Name | ValueID | Value 

100 | Color | 10000 | Black 
101 | Size | 10005 | Large 

Результат должен быть таким:

Name_100 | Color | Name_101 | Size | 

10000  | Black | 10005  | Large | 
+0

Можете ли вы показать ВАШ таблицу, данные образца и желаемые результаты? Можете ли вы также объяснить, что означает «не работает»? –

+0

@Aaron: «Таблица» представляет собой список из числа X строк результатов с 4 столбцами, весь запрос не работает. Может ли Pivot справиться с этим? –

+1

Я понятия не имею. Вот почему я попросил более подробную информацию о том, что вы пытаетесь выполнить. Можете ли вы показать свою структуру таблиц ('CREATE TABLE'), образцы данных и то, что вы хотите, чтобы результат запроса выглядел? В противном случае я понятия не имею, что такое «это», что, как ожидается, будет обрабатываться. –

ответ

1

Возможно, что-то подобное.

Это будет работать, только если столбец имени уникален. Если нет, вы можете добавить к нему идентификатор.

Так первые несколько тестовых данных:

CREATE TABLE tblValues 
    (
     ID INT, 
     Name VARCHAR(100), 
     ValueID INT, 
     Value VARCHAR(100) 
    ) 

INSERT INTO tblValues 
VALUES 
    (100,'Color',10000,'Black'), 
    (101,'Size',10005,'Large') 

Затем вам нужно, чтобы получить столбцы для поворота на:

DECLARE @cols VARCHAR(MAX) 
;WITH CTE AS 
(
    SELECT 
     'Name_'+CAST(tbl.ID AS VARCHAR(100)) AS Name, 
     'Name_'+CAST(tbl.ID AS VARCHAR(100)) AS Sort, 
     tbl.ID 
    FROM 
     tblValues AS tbl 
    UNION ALL 
    SELECT 
     tbl.Name, 
     'Value_'+CAST(tbl.ID AS VARCHAR(100)) AS Sort, 
     tbl.ID 
    FROM 
     tblValues AS tbl 
) 
SELECT 
    @cols = COALESCE(@cols + ','+QUOTENAME(Name), 
       QUOTENAME(Name)) 
FROM 
    CTE 
ORDER BY 
    CTE.ID, 
    CTE.Sort 

Тогда декларирование и выполнения динамического SQL, как это:

DECLARE @query NVARCHAR(4000)= 
N'SELECT 
    * 
FROM 
(
    SELECT 
     ''Name_''+CAST(tbl.ID AS VARCHAR(100)) AS pivotName, 
     CAST(tbl.ValueID AS VARCHAR(100)) AS name 
    FROM 
     tblValues AS tbl 
    UNION ALL 
    SELECT 
     tbl.Name AS pivotName, 
     tbl.Value AS name 
    FROM 
     tblValues AS tbl 
) AS p 
PIVOT 
(
    MAX(name) 
    FOR pivotName IN ('[email protected]+') 
) AS pvt' 

EXECUTE(@query) 

Тогда в моем случае я откажусь от таблицы, которую создал

DROP TABLE tblValues 

Редактировать

Или вы случае это должно быть что-то вроде этого:

Сначала столбцы:

DECLARE @cols VARCHAR(MAX) 
;WITH CTE AS 
(
    SELECT 
     'Name_'+CAST(tbl.ID AS VARCHAR(100)) AS Name, 
     'Name_'+CAST(tbl.ID AS VARCHAR(100)) AS Sort, 
     tbl.ID 
    FROM 
     [Table] AS tbl 
    WHERE 
     tbl.OptionID = 1000000 
    UNION ALL 
    SELECT 
     tbl.Name, 
     'Value_'+CAST(tbl.ID AS VARCHAR(100)) AS Sort, 
     tbl.ID 
    FROM 
     [Table] AS tbl 
    WHERE 
     tbl.OptionID = 1000000 
) 
SELECT 
    @cols = COALESCE(@cols + ','+QUOTENAME(Name), 
       QUOTENAME(Name)) 
FROM 
    CTE 
ORDER BY 
    CTE.ID, 
    CTE.Sort 

Тогда динамический SQL.

DECLARE @query NVARCHAR(4000)= 
N'SELECT 
    * 
FROM 
(
    SELECT 
     ''Name_''+CAST(tbl.ID AS VARCHAR(100)) AS pivotName, 
     CAST(tbl.ValueID AS VARCHAR(100)) AS name 
    FROM 
     [Table] AS tbl 
    WHERE 
     tbl.OptionID = 1000000 
    UNION ALL 
    SELECT 
     tbl.Name AS pivotName, 
     tbl.Value AS name 
    FROM 
     [Table] AS tbl 
    WHERE 
     tbl.OptionID = 1000000 
) AS p 
PIVOT 
(
    MAX(name) 
    FOR pivotName IN ('[email protected]+') 
) AS pvt' 

EXECUTE(@query) 

Вам не нужно создавать таблицу или бросать стол. Это было только потому, что у меня не было таблицы в моей базе данных и что если кто-то хочет запустить этот пример.

+0

Благодарим вас за ответ. Является ли создание таблицы 'tblValues' необходимой, когда исходная таблица уже имеет эти значения? (как показано в инструкции 'SELECT' в вопросе?) –

+0

Я обновил ответ. Если вы согласны с ответом, вы можете принять его. – Arion

1

Если вы хотите использовать Pivot таблицы с переменным числом столбцов, то я бы предложил использовать что-то по строкам;

DECLARE @cols VARCHAR(4000) 
    DECLARE @query VARCHAR(8000) 
    SELECT @cols = STUFF((SELECT DISTINCT 
      '],[' + Name 
         FROM Table 
         ORDER BY '],[' + Name 
         FOR XML PATH('') 
        ), 1, 2, '') + ']' 

    SET @query = 
    'SELECT * FROM 
    (
     SELECT col1, col2, col3, whateverColYourInterestedIn, Name, Value 
     FROM Table 
    )t 
    PIVOT (MAX(Value) FOR Name 
    IN ('[email protected]+')) AS pvt' 

    EXECUTE (@query) 

Это, вероятно, не совсем верно, но, надеюсь, это будет отправной точкой для вас.

Для получения дополнительной информации см. Ссылки, такие как this или this.

+0

Это то, что я бы предложил, но ваш запрос требует некоторой очистки. У вас есть отсутствующая одинарная кавычка в вашем SELECT DISTINCT, и выполнение ORDER BY в подзапросе - это не-нет. SQL Server должен фактически стонать об этом. :) – FarligOpptreden

+0

Спасибо за примечание. Я добавил недостающую цитату. В подзапросе нет ORDER BY, он используется в параметре I, передаваемом в STUFF. Вот как все примеры, которые я видел для создания динамических списков столбцов, и я сам использовал его. Я согласен с тем, что код может не работать, но, надеюсь, он предоставит OP некоторые идеи, а связанные ссылки помогут им объединить остальных и заставить их работать. –

+0

Я действительно обращался к ORDER BY в запросе, переданном в STUFF. Я несколько раз стонал от SQL Server, и лучшим решением, которое я мог бы собрать, было поставить SELECT в CTE с помощью ROW_NUMBER() OVER (ORDER BY ...) взлома, чтобы упорядочить данные, а затем просто выберите соответствующие столбцы из CTE в STUFF. Надеюсь, что это имеет смысл ...: P Я поддержал ваш ответ, поскольку я считаю, что это самая динамичная реализация. Вы можете попробовать вызвать sp_ExecuteSQL, чтобы убедиться, что путь запроса также кэшируется ... – FarligOpptreden