[英]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.