2016-11-22 2 views
0

Я искал ответ на этот вопрос и нашел вопросы, похожие на мои собственные, однако у меня нет столбца «ColumnHeader», чтобы указать, какое поле запись должна войти. Пример:T-SQL Как «сгладить» верхние 3 строки в одну строку

TSQL Pivot without aggregate function

trying to flatten rows into columns

Fetching Columns of a multiple rows in one row

Моя проблема, таким образом, - У меня есть данные в этом формате (выбранной в качестве верхнего 3 результата из запроса рекомендации продукта):

------------------------------ 
CustID | StyleNo | Brand | ID 
------------------------------ 
    1 | ABC | BrandA| 1 
------------------------------ 
    1 | DEF | BrandB| 2 
------------------------------ 
    1 | GHI | BrandC| 3 
------------------------------ 
    2 | JKL | BrandA| 4 
------------------------------ 
    2 | MNO | BrandB| 5 
------------------------------ 
    2 | PQR | BrandD| 6 
------------------------------ 

Что я хотел бы сделать так:

----------------------------------------------------------------- 
CustID | StyleNo1| StyleNo2| StyleNo3 | Brand1 | Brand2 | Brand3 
----------------------------------------------------------------- 
    1 | ABC | DEF | GHI | BrandA | BrandB | BrandC 
----------------------------------------------------------------- 
    2 | JKL | MNO | PQR | BrandA | BrandB | BrandD 
----------------------------------------------------------------- 

Чтобы моя программа просто прочитала ряд рекомендаций для каждого клиента.

Что я пытался сделать, это PIVOT, но мне нечего на самом деле заполнить. Я также попытался выполнить Min(Case...When...Then...End), как описано во втором связанном вопросе, но, как указано, у меня нет ссылки на столбец «Заголовок».

Колонка ID на данный момент является несущественной, но может помочь решить эту проблему. Он не нужен в конечном результате.

настоящее время я использую SQLServer 2012

+0

попробовать материал https://msdn.microsoft.com/en-us/library/ms188043.aspx – happymacarts

+0

@happymacarts STUFF, кажется, чтобы я мог разобрать данные в список разделенных запятыми значения, которые мне пришлось бы декодировать в интерфейсе. Есть ли более простой способ просто предоставить табличные данные в описанном формате? Пожалуйста, дайте мне знать, если я не совсем понимаю ваше решение. –

+0

возможно, попробуйте группу или посмотрите на группы группировки. Думаю, я неправильно понял ваш oP – happymacarts

ответ

2

С помощью функции окна row_number() и условной агрегации

Select CustID 
     ,StyleNo1 = max(case when RN=1 then StyleNo else null end) 
     ,StyleNo2 = max(case when RN=2 then StyleNo else null end) 
     ,StyleNo3 = max(case when RN=3 then StyleNo else null end) 
     ,Brand1 = max(case when RN=1 then Brand else null end) 
     ,Brand2 = max(case when RN=2 then Brand else null end) 
     ,Brand3 = max(case when RN=3 then Brand else null end) 
From (
     Select *,RN = Row_Number() over (Partition By CustID Order by StyleNo,Brand) 
     From YourTable 
     ) A 
Where RN<=3 
Group By CustID 

Возвращает

enter image description here

+0

Отличный ответ, спасибо за этот синтаксис. –

+0

@TramelJones С удовольствием помогите –

1

То, что вы делаете, называется «поворотное »- для этого вы можете использовать PIVOT. Лучший способ ИМХО - использовать подход, о котором говорит Джефф Моден в this article.

WITH idSort AS 
(
    SELECT *, rn = ROW_NUMBER() OVER (PARTITION BY CustID ORDER BY ID) FROM @yourTable 
) 
SELECT 
    CustID, 
    StyleNo1 = MAX(CASE rn WHEN 1 THEN StyleNo END), 
    StyleNo2 = MAX(CASE rn WHEN 2 THEN StyleNo END), 
    StyleNo3 = MAX(CASE rn WHEN 3 THEN StyleNo END), 
    Brand1 = MAX(CASE rn WHEN 1 THEN Brand END), 
    Brand2 = MAX(CASE rn WHEN 2 THEN Brand END), 
    Brand3 = MAX(CASE rn WHEN 3 THEN Brand END) 
FROM idSort 
GROUP BY CustID; 
+1

Спасибо за статью! Хороший совет –

0

Другой подход может быть применен для использования CTE и Cross Apply.

CREATE TABLE #UnFlattenedData 
    (
     CustID TINYINT , 
     StyleNo CHAR(3) , 
     Brand CHAR(6) , 
     ID TINYINT 
    ); 

INSERT INTO #UnFlattenedData 
     (CustID, StyleNo, Brand, ID) 
VALUES (1, -- CustID - tinyint 
      'ABC', -- StyleNo - char(3) 
      'BrandA', -- Brand - char(6) 
      1 -- ID - tinyint 
     ), 
     (1, -- CustID - tinyint 
      'DEF', -- StyleNo - char(3) 
      'BrandB', -- Brand - char(6) 
      2 -- ID - tinyint 
     ), 
     (1, -- CustID - tinyint 
      'GHI', -- StyleNo - char(3) 
      'BrandC', -- Brand - char(6) 
      3 -- ID - tinyint 
     ), 
     (2, -- CustID - tinyint 
      'JKL', -- StyleNo - char(3) 
      'BrandA', -- Brand - char(6) 
      4 -- ID - tinyint 
     ), 
     (2, -- CustID - tinyint 
      'MNO', -- StyleNo - char(3) 
      'BrandB', -- Brand - char(6) 
      5 -- ID - tinyint 
     ), 
     (2, -- CustID - tinyint 
      'PQR', -- StyleNo - char(3) 
      'BrandD', -- Brand - char(6) 
      6 -- ID - tinyint 
     ); 
WITH cte 
      AS (SELECT * , 
         ROW_NUMBER() OVER (PARTITION BY u1.CustID ORDER BY u1.ID) AS R1 
       FROM  #UnFlattenedData AS u1 
      ), 
     u1 
      AS (SELECT C1.CustID , 
         U1.StyleNo , 
         U1.Brand 
       FROM  cte AS C1 
         INNER JOIN #UnFlattenedData AS U1 ON U1.CustID = C1.CustID 
                  AND U1.ID = C1.ID 
       WHERE C1.R1 = 1 
      ), 
     u2 
      AS (SELECT C1.CustID , 
         U1.StyleNo , 
         U1.Brand 
       FROM  cte AS C1 
         INNER JOIN #UnFlattenedData AS U1 ON U1.CustID = C1.CustID 
                  AND U1.ID = C1.ID 
       WHERE C1.R1 = 2 
      ), 
     u3 
      AS (SELECT C1.CustID , 
         U1.StyleNo , 
         U1.Brand 
       FROM  cte AS C1 
         INNER JOIN #UnFlattenedData AS U1 ON U1.CustID = C1.CustID 
                  AND U1.ID = C1.ID 
       WHERE C1.R1 = 3 
      ) 
    SELECT u1.CustID , 
      u1.StyleNo AS StyleNo1 , 
      u2.StyleNo AS StyleNo2 , 
      u3.StyleNo AS StyleNo3 , 
      u1.Brand AS Brand1 , 
      u2.Brand AS Brand2 , 
      u3.Brand AS Brand3 
    FROM u1 
      CROSS APPLY (SELECT * 
          FROM  u2 
          WHERE  u2.CustID = u1.CustID 
         ) AS u2 
      CROSS APPLY (SELECT * 
          FROM  u3 
          WHERE  u3.CustID = u1.CustID 
         ) AS u3; 

ResultSet

+0

Имеет ли использование CTE с «CROSS APPLY» какое-либо преимущество в производительности над кросс-вкладкой? (принятый ответ) –

Смежные вопросы