Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
T-SQL如何将前3行“展平”为一行_Sql_Sql Server_Tsql - Fatal编程技术网

T-SQL如何将前3行“展平”为一行

T-SQL如何将前3行“展平”为一行,sql,sql-server,tsql,Sql,Sql Server,Tsql,我搜索了这个问题的答案,并找到了与我类似的问题,但是我没有一个ColumnHeader列来指示记录应该进入哪个字段。例: 因此,我的问题是——我选择了这种格式的数据作为产品推荐查询的前三名结果: ------------------------------ CustID | StyleNo | Brand | ID ------------------------------ 1 | ABC | BrandA| 1 ------------------------

我搜索了这个问题的答案,并找到了与我类似的问题,但是我没有一个ColumnHeader列来指示记录应该进入哪个字段。例:

因此,我的问题是——我选择了这种格式的数据作为产品推荐查询的前三名结果:

 ------------------------------
 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
 -----------------------------------------------------------------
为了让我的程序能够简单地阅读每个客户的推荐行

我所尝试的是一个支点——但是我没有什么可以真正聚合的。我还尝试了MinCase…When…Then…End,如第二个链接问题中所述,但如上所述,我没有引用标题列

ID列暂时是完全无关紧要的,但它可能有助于解决这个问题。最终结果并不需要它


我目前正在使用SQLServer 2012,它具有窗口函数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
返回


你所做的就是所谓的旋转——为此你可以使用。IMHO的一个更好的方法是使用Jeff Moden在中谈到的方法


其他方法可以使用CTE和交叉应用

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;

try stuff@happyCarts stuff似乎使我能够将数据解析为逗号分隔的值列表,我必须在前端对其进行解码。有没有一种更简单的方法,可以按照我描述的格式提供表格数据?如果我不太了解您的解决方案,请告诉我。也许可以尝试分组方式或查看分组集。我想我误解了您的oPis目标表结构已修复?您总是有3条记录要放平,或最多3条,也可以是任意数字。目标表最多有3条建议,我的select语句将在使用数据之前检查第2条或第3条建议是否为空。感谢您的文章!好的tip@TramelJones乐于帮助使用交叉应用的CTE是否比交叉选项卡有任何性能优势?公认的答案
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;