4

次のような SQL テーブルがあります。

CC     Descr  C_NO     Vol   Wt

2050   Des1   123      20    40
2060   Des2   123      30    50
2050   Des1   125      20    40
2060   Des2   125      30    50
2050   Des1   126      20    40

次のような出力が必要です。

2050
    Des1

 123
    20
    40
 125
    20
    40   
 126
    20
    40

2060
    Des2

 123
    30
    50
 125
    30
    50

TSQLコードを使用してそれを行うにはどうすればよいですか?

常に同様の Descr 値を持つすべての同様の CC 値について、出力セクションに書き込まれたシーケンス内の特定の CC 値に関連するすべての C_No、Vol、および Wt 値を示します。

4

4 に答える 4

2

これを試して

 DECLARE @t TABLE
(
    CC BIGINT,
    Descr NVARCHAR(10),
    C_NO INT,
    Vol SMALLINT,
    WT SMALLINT
)

INSERT INTO @t(CC,Descr,C_NO,Vol,WT)
VALUES  (2050,'Des1',123,20,40)
       ,(2060,'Des2',123,30,50)
       ,(2050,'Des1',125,20,40)
       ,(2060,'Des2',125,30,50)
       ,(2050,'Des1',126,20,40)



;WITH CTE1 AS(
    SELECT 
        t1.CC
        ,t1.Descr
        ,MergedColumn = STUFF(
            (SELECT 
                    ',' 
                    + CAST(C_NO AS VARCHAR(10)) + '/' + CAST(Vol AS VARCHAR(10)) + '/' + CAST(Wt AS VARCHAR(10)) 
            FROM @t AS t2
            WHERE t2.CC=t1.CC AND t2.Descr=t2.Descr
            FOR XML PATH('')),1,1,'')
FROM  @t t1
GROUP BY t1.CC,t1.Descr) 
,CTE2 AS
(
    SELECT
            X.CC
            ,X.Descr
            ,Y.SplitDataByComma         
    FROM
        (
            SELECT 
                    *,
                    CAST('<X>'+REPLACE(F.MergedColumn,',','</X><X>')+'</X>' AS XML) AS xmlfilter 
            FROM CTE1 F
        )X
    CROSS APPLY
    ( 
        SELECT fdata.D.value('.','varchar(50)') AS SplitDataByComma 
        FROM X.xmlfilter.nodes('X') AS fdata(D)
    )Y
)
,CTE3 AS
(
    SELECT
            X.CC
            ,X.Descr
            ,Y.SplitDataBySlash         
            , X.SplitDataByComma AS GrpID
            ,ROW_NUMBER() OVER( PARTITION  BY X.SplitDataByComma ORDER BY X.CC,X.Descr ) AS Rn
            ,X.SplitDataByComma + CAST(CC AS Varchar(200)) + CAST(Descr AS Varchar(200))   CC_Descr 
    FROM
        (
            SELECT 
                    *,
                    CAST('<X>'+REPLACE(F.SplitDataByComma,'/','</X><X>')+'</X>' AS XML) AS xmlfilter 
            FROM CTE2 F
        )X
    CROSS APPLY
    ( 
        SELECT fdata.D.value('.','varchar(50)') AS SplitDataBySlash 
        FROM X.xmlfilter.nodes('X') AS fdata(D)
    )Y
)
,CTE4 AS
(
    SELECT  
        Rn = ROW_NUMBER() OVER(PARTITION BY CC ORDER BY CC)     
        ,CC
        ,Descr      
        ,CASE WHEN  Rn = 1 THEN CAST (SplitDataBySlash AS VARCHAR(10)) ELSE ' '  END C_NO
        ,CASE WHEN  Rn = 1 THEN ' ' ELSE CAST (SplitDataBySlash AS VARCHAR(10)) END Vol_Wt
        ,GrpID  
    FROM Cte3
)
,CTE5 AS(
SELECT 
        CC =  CASE WHEN Rn > 1 THEN ' ' ELSE CAST(CC AS Varchar(200)) END 
        ,Descr =  CASE WHEN Rn > 1 THEN ' ' ELSE CAST(Descr AS Varchar(200)) END 
        ,C_NO
        ,Vol_Wt
        ,GrpID  
FROM Cte4)

SELECT  
          CHAR(10)      
        + REPLICATE(SPACE(1),10) 
        + CAST(CC as VARCHAR(100)) 
        + CHAR(10) 
        + REPLICATE(SPACE(1),15) 
        + Descr
        + CHAR(10)
        + REPLICATE(SPACE(1),10)
        + C_NO
        + CHAR(10) 
        + REPLICATE(SPACE(1),15)
        + Vol_Wt
FROM CTE5

テキスト モード (CTRL + T) では、結果は次のようになります。

     2050
           Des1
      123
           20           
           40
      125
           20           
           40
      126
           20
           40

      2060
           Des2
      123
           30           
           50
      125
           30
           50

そしてグリッドモード(CTRL + D) では、結果は

(No column name)
      2050
           Des1
      123 
           20           
           40
      125           
           20           
           40
      126
           20
           40

      2060
           Des2
      123
           30
           50
      125
           30
           50

ただし、SQL Server (または任意のデータベース) は、他の人が話したようにフォーマットを行う場所ではありません。問題を調べてください。

于 2012-09-10T09:43:16.633 に答える
1

私はこれをしません。TSQL を使用してデータを取得し、そのデータをアプリケーション コードでフォーマットします。
ただし、クエリ アナライザーで作業していて、そこに出力が必要な場合は、次のことを試すことができます。

DECLARE mytable_cursor CURSOR FOR 
SELECT CC, Descr, C_NO, Vol, Wt
FROM myTable
ORDER BY CC, Descr, C_NO

OPEN mytable_cursor;

FETCH NEXT FROM mytable_cursor 
INTO @CC, @Descr, @C_NO, @Vol, @Wt

SET @oCC = @CC
SET @oDescr = @Descr
SET @oC_NO = @C_NO

WHILE @@FETCH_STATUS = 0
BEGIN
    PRINT @CC;
    WHILE @@FETCH_STATUS = 0 AND @oCC = @CC
    BEGIN    
        PRINT '    ' + @Descr;
        WHILE @@FETCH_STATUS = 0 AND @oDescr = @Descr
        BEGIN
            PRINT ' ' + @C_NO;
            WHILE @@FETCH_STATUS = 0 AND @oC_NO = @C_NO
            BEGIN
                PRINT '    ' + @Vol;
                PRINT '    ' + @WT;

                FETCH NEXT FROM mytable_cursor 
                INTO @CC, @Descr, @C_NO, @Vol, @Wt

            END
            SET @oC_NO = @C_NO
        END             
        SET @oDescr = @Descr
    END             
    SET @oCC = @CC
END     
CLOSE mytable_cursor;
DEALLOCATE mytable_cursor;

または、GROUP BY ... WITH ROLLUP と CASE WHEN を使用して、1 つのクエリで結果を取得することもできます。

書式設定が確実に表示されるように、スペースの代わりにダッシュを使用した例を次に示します。

SELECT (CASE
        WHEN Descr IS NULL THEN CC
        WHEN C_NO IS NULL THEN '----' + Descr
        WHEN Vol IS NULL THEN '--' + C_NO
        WHEN Wt IS NULL THEN '------' + Vol
        ELSE '------' + Wt
        END)
FROM
    (SELECT CC, Descr, C_NO, Vol, Wt
    FROM my
    GROUP BY CC, Descr, C_NO, Vol, Wt
    WITH ROLLUP) AS x
WHERE CC IS NOT NULL
ORDER BY CC, Descr, C_NO, Vol, Wt
于 2012-09-07T17:25:33.157 に答える
0

データを階層順に表すための最良の方法の1つは、XMLを使用することです。さらに、多くの場合、XMLの使用は優れたパフォーマンスと関連しています。

サンプル情報とこのコードの平和を使用して:

;WITH DistinctValues (CC,Descr ) AS
(
    SELECT DISTINCT CC,Descr 
    FROM @TableOne
)
SELECT  (
            SELECT  CC AS "CC/@CC"
                   ,Descr AS "CC/Descr"
                   ,(
                        SELECT C_NO AS "C_NO/@C_NO",
                               Vol AS "C_NO/Vol",
                               Wt AS "C_NO/Wt"
                        FROM @TableOne AS Data
                        WHERE Data.CC=DV.CC AND Data.Descr=DV.Descr
                        FOR XML PATH(''),TYPE
                   ) AS  "CC"
            FROM DistinctValues AS DV
            FOR XML PATH(''),TYPE
        )
FOR XML PATH('Source'),TYPE

次の結果が得られます(上記のステートメントによる1行の戻りの形式で):

<Source>
  <CC CC="2050">
    <Descr>Des1</Descr>
    <C_NO C_NO="123">
      <Vol>20</Vol>
      <Wt>40</Wt>
    </C_NO>
    <C_NO C_NO="125">
      <Vol>20</Vol>
      <Wt>40</Wt>
    </C_NO>
    <C_NO C_NO="126">
      <Vol>20</Vol>
      <Wt>40</Wt>
    </C_NO>
  </CC>
  <CC CC="2060">
    <Descr>Des2</Descr>
    <C_NO C_NO="123">
      <Vol>30</Vol>
      <Wt>50</Wt>
    </C_NO>
    <C_NO C_NO="125">
      <Vol>30</Vol>
      <Wt>50</Wt>
    </C_NO>
  </CC>
</Source>

T-SQLのXML関数をXML言語構造と組み合わせると、出力データ形式のさまざまなバリエーションが可能になることに注意してください。1つまたは複数のノードを使用し、データを属性またはノードテキストとして表すことができます。これを好きなように組み合わせて、アプリケーションレベルで作業するのが最も簡単だと感じます。

以前のXML構造を生成するために使用したコード全体(コピーして貼り付けるだけ)は次のとおりです。

DECLARE @TableOne TABLE
(
    CC BIGINT,
    Descr NVARCHAR(10),
    C_NO INT,
    Vol SMALLINT,
    WT SMALLINT
)

INSERT INTO @TableOne(CC,Descr,C_NO,Vol,WT)
VALUES  (2050,'Des1',123,20,40)
       ,(2060,'Des2',123,30,50)
       ,(2050,'Des1',125,20,40)
       ,(2060,'Des2',125,30,50)
       ,(2050,'Des1',126,20,40)

;WITH DistinctValues (CC,Descr ) AS
(
    SELECT DISTINCT CC,Descr 
    FROM @TableOne
)
SELECT  (
            SELECT  CC AS "CC/@CC"
                   ,Descr AS "CC/Descr"
                   ,(
                        SELECT C_NO AS "C_NO/@C_NO",
                               Vol AS "C_NO/Vol",
                               Wt AS "C_NO/Wt"
                        FROM @TableOne AS Data
                        WHERE Data.CC=DV.CC AND Data.Descr=DV.Descr
                        FOR XML PATH(''),TYPE
                   ) AS  "CC"
            FROM DistinctValues AS DV
            FOR XML PATH(''),TYPE
        )
FOR XML PATH('Source'),TYPE

これは魅力のように機能し、Microsoft SQL Server ManagementStudio2012でテストされています。

于 2012-09-09T08:06:02.497 に答える
0

これは tsql コードでは実行できません。この種のことをアプリケーション コードで行う必要があります。

于 2012-09-07T17:09:56.907 に答える