簡體   English   中英

SQL 服務器 Pivot with Inner Join

[英]SQL Server Pivot with Inner Join

我有兩張桌子

表格1:

    -----------------------------------------------
    |  iFirstID  |  fkSomeID  |  cText  | bStatus |
    |     1      |     59     |  'blah' |    1    |
    |     2      |     100    |  'text' |    0    |
    -----------------------------------------------

表 2:

    -------------------------------------------------------------------------
    |  iSecondID  |   fkFirstID  |   fkOtherID  |  cSomeText  |  bSomeBool  |
    |      1      |       1      |       1      |    "text"   |      1      |
    |      2      |       1      |       2      | "more text" |      0      |
    |      3      |       1      |       3      | "more text" |      0      |
    |      4      |       2      |       1      |   "blah"    |      1      |
    |      5      |       2      |       2      |   "test"    |      1      |
    |      6      |       2      |       3      |   "data"    |      0      |
    -------------------------------------------------------------------------

我想寫一個查詢,它將根據上面的內容返回以下數據集

結果:

    -----------------------------------------------------------------------------------------------------
    |  fkFirstID  |  fkSomeID  |  cText  |  bSomeBool[1]  |  bSomeBool[2]  |  bSomeBool[3]  |  bStatus  |   
    |      1      |     59     |  'blah' |      1         |       0        |        0       |     0     |
    |      2      |    100     |  'text' |      1         |       1        |        0       |     0     |
    -----------------------------------------------------------------------------------------------------

正如您在上面看到的,對於表 2 中具有相同 fkFirstID 的每一行,都會報告 bSomeBool。

我根本不熟悉樞軸,但我很確定這是我需要用來完成我正在尋找的東西。 我在網上查看了一些建議(例如: SQL 服務器連接表和 pivot ),但我無法理解它,因為大多數與我想要完成的有點不同。

沒有包括第三個表,這是 fkOtherID 發揮作用的地方。 我們可以假設這個表有兩列:iOtherID 和 cColumnName

在表 2 中,對於相同的 fkFirstID,我們永遠不會有重復的 fkOtherID。 因此對於每個 fkOtherID 值,我們將 go 到表 3,並將列名稱設置為 cColumnName。 不確定這是否會對最終解決方案產生太大影響。

我試過使用內部聯接,但結果是它只會查看表 2 的第一行。

我嘗試使用 Group By,但它一直為我的其他列返回錯誤,因為它們不是聚合 function 的一部分,但我仍然認為這不是我想要的,因為我認為它會返回兩行,一個帶有 1,另一個帶有 bSomeBool 列的 0。

正如我在評論中所說,它更像是一個動態的SELECT問題,而不是PIVOT問題。 下面是我將如何使用動態 SQL 進行操作。

CREATE TABLE dataOne (
  iFirstID int
  , fkSomeID int
  , cText nvarchar(50)
  , bStatus int
);

INSERT INTO dataOne (iFirstID, fkSomeID, cText, bStatus)
VALUES 
  (1,59,'blah',1)
  , (2,100,'text',0)
;

CREATE TABLE dataTwo (
  iSecondID int
  , fkFirstID int
  , fkOtherID int
  , cSomeText nvarchar(50)
  , bSomeBool int
);

INSERT INTO dataTwo (iSecondID, fkFirstID, fkOtherID, cSomeText, bSomeBool)
VALUES
  (1,1,1,'text',1)
  , (2,1,1,'more text',0)
  , (3,1,1,'more text',0)
  , (4,2,1,'blah',1)
  , (5,2,1,'test',1)
  , (6,2,1,'data',0)
;

--Get the maximum number of events so we know how many columns to create.
DECLARE @maxBools int;
SET @maxBools = (
  SELECT MAX(d2.row_num)
  FROM (
    SELECT ROW_NUMBER() OVER(PARTITION BY fkFirstID ORDER BY fkOtherID) as row_num
    FROM dataTwo
  ) as d2 );

--Create a variable to hold the dynamic query.
DECLARE @sqlText nvarchar(max);

--Create the first part of the SELECT statment with place holders
--where we can insert columns ({{0}}) and JOINS ({{1}})
SET @sqlText = '
  WITH prelim as (
    SELECT *, ROW_NUMBER() OVER(PARTITION BY fkFirstID ORDER BY fkOtherID) as row_num
    FROM dataTwo
  )
  SELECT DISTINCT d1.iFirstID, d1.fkSomeID, d1.cText, d1.bStatus
    {{0}}
  FROM dataOne as d1
    {{1}}
  ';

--Setup loop variables.
DECLARE @loopCount int = 1;
DECLARE @loopCText nvarchar(50);

WHILE (@loopCount <= @maxBools)
BEGIN
  --Get a string for the loop count... pad it with zeros if multi-digits.
  SET @loopCText = RIGHT(
    '0000000000' + CAST(@loopCount as nvarchar(10))
    , LEN(CAST(@maxBools as nvarchar(50)))
  );

  --Add a SELECT entry for this loop instance.
  SET @sqlText = REPLACE(@sqlText, '{{0}}', '
    , d2' + @loopCText + '.bSomeBool as bSomeBool' + @loopCText + '
    {{0}}
  ');

  --Add a JOIN entry for this loop instance.
  SET @sqlText = REPLACE(@sqlText, '{{1}}', '
    LEFT OUTER JOIN prelim as d2' + @loopCText + '
      ON d2' + @loopCText + '.fkFirstID = d1.iFirstID
      AND d2' + @loopCText + '.row_num = ' + CAST(@loopCount as nvarchar(10)) + '
    {{1}}
  ');

  --SELECT @sqlText;  --For debugging
  SET @loopCount = @loopCount + 1;
END

--Post Loop Cleanup... remove template place holders.
SET @sqlText = REPLACE(@sqlText, '{{0}}', '');
SET @sqlText = REPLACE(@sqlText, '{{1}}', '');

EXEC(@sqlText);




iFirstID fkSomeID 正文 b狀態 bSomeBool1 bSomeBool2 bSomeBool3
1個 59 廢話 1個 1個 0 0
2個 100 文本 0 1個 1個 0

小提琴

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM