Sql-Server

JOIN 3 沒有 Union ALL 的表,也沒有具有多個 ID 的嵌套查詢

  • December 7, 2016

不確定這是否可能,但我想在沒有UNION ALL或嵌套查詢的情況下加入具有多個 ID 的多個表。您可以在此處查看相關問題,該問題在表格視圖中顯示所有內容。我想創建一個table view但不允許使用上面提到的內容。我已經想出瞭如何使用UNION ALL.

所以,我有一個Main表,它引用了一個名為Fact. 該Fact表包含可由 、 或 (revision) 引用LanguageIDClientID數據StatusIDMain和表通過稱為(為簡單起見未顯示)Fact的中間表​​相關聯。FactLink

MainView我想得到的最終結果可索引表如下所示:

主視圖

MainID | StatusOrder | LanguageID | ClientID | Description   | Disclaimer  | Other
-------+-------------+------------+----------+---------------+-------------+------
50     | 10          | 1          | 1        | Some text     | Disclaimer1 | Blah
50     | 10          | 2          | 1        | Otro texto    | NULL        | Blah
50     | 20          | 1          | 2        | Modified text | NULL        | Blah
55     | 10          | 1          | 1        | Some text 2   | Disclaimer2 | Blah Blah
55     | 10          | 1          | 2        | NULL          | Disclaimer3 | Blah Blah

DROP TABLE IF EXISTS #main
CREATE TABLE #main
(
   ID INT NOT NULL,
   DescriptionID INT NOT NULL,
   DisclaimerID INT NOT NULL,
   Other NVARCHAR(500)
)

Drop table if exists #fact
CREATE TABLE #fact
(
   FactID INT NOT NULL,
   LanguageID INT NOT NULL,
   StatusID INT NOT NULL,
   ClientID INT NOT NULL,
   Description NVARCHAR(MAX)
)

DROP TABLE IF EXISTS #status
CREATE TABLE #status
(
   StatusID INT NOT NULL,
   [Order] INT NOT NULL
)

INSERT INTO #main
   (ID, DescriptionID, DisclaimerID, Other)
   VALUES
   (50, 1, 2, 'Blah'),
   (55, 4, 3, 'Blah Blah')

INSERT INTO #fact
   (FactID, LanguageID, StatusID, ClientID, Description)
   VALUES
   (1, 1, 1, 1, N'Some text'),
   (1, 2, 1, 1, N'Otro texto'),
   (1, 1, 3, 2, N'Modified text'),
   (2, 1, 1, 1, N'Disclaimer1'),
   (3, 1, 1, 1, N'Disclaimer2'),
   (3, 1, 2, 1, N'Disclaimer3'),
   (4, 1, 1, 1, N'Some text 2')

INSERT INTO #status
   (StatusID, [Order])
   VALUES
   (1, 10),
   (2, 100),
   (3, 20)

這是我到目前為止所擁有的。但它不包括最後一個條目,也沒有考慮StatusOrder. 我不知道從這裡去哪裡。

SELECT
   t.ID, t.Other,
   fDescription.Description,
   fDisclaimer.Description Disclaimer,
   COALESCE(fDescription.LanguageID, fDisclaimer.LanguageID) LanguageID,
   COALESCE(fDescription.ClientID, fDisclaimer.ClientID) ClientID,
   COALESCE(fDescription.StatusID, fDisclaimer.StatusID) StatusID
FROM #main t
JOIN #fact fDescription
   ON fDescription.FactID = t.DescriptionID
LEFT OUTER JOIN #fact fDisclaimer
   ON fDisclaimer.FactID = t.DisclaimerID
   AND fDisclaimer.ClientID = fDescription.ClientID
   AND fDisclaimer.LanguageID = fDescription.LanguageID
   AND fDisclaimer.StatusID = fDescription.StatusID

我會按要求回答問題,但我希望它不會解決您的實際問題。您希望將您在另一篇文章中的查詢轉換為可以轉換為索引視圖的查詢。我看到的最大問題是您的數據模型要求將“事實”表的多行中的數據組合成單行。這樣的要求與索引視圖功能作鬥爭。許多T-SQL 限制似乎是圍繞停止這種類型的操作(以及其他操作)而設計的:

索引視圖限制

對於您的問題,該列表中最重要的條目是對 MAX、MIN、自聯接、子查詢、APPLY 和 UNPIVOT 的禁止。所有這些都可用於重寫您的 UNION ALL 查詢,但它們都不允許在索引視圖中使用。有一種方法可以重寫它,但你只會陷入更深的困境。您從以下查詢開始:

SELECT
 Main.ID,
 s.[Order],
 f.LanguageID,
 f.ClientID,
 f.Description,
 NULL Disclaimer,
 Main.Other
FROM Main
JOIN Fact f
ON f.FactID = Main.DescriptionID
JOIN Status s ON s.StatusID = f.StatusID
UNION ALL
SELECT
 Main.ID,
 s.[Order],
 f.LanguageID,
 f.ClientID,
 NULL Description,
 f.Description Disclaimer,
Main.Other
FROM Main
JOIN Fact f
ON f.FactID = Main.DisclaimerID
JOIN Status s ON s.StatusID = f.StatusID;

至少有一種方法可以以有效的索引視圖定義的方式重寫該查詢。首先創建一個只有兩行的虛擬表:

CREATE TABLE DIM_NUMBERS (NUM INT NOT NULL);
INSERT INTO DIM_NUMBERS VALUES (1), (2);

然後,您可以像這樣定義您的視圖:

CREATE VIEW dbo.X_VIEW
WITH SCHEMABINDING  
AS  
SELECT
 Main.ID,
 s.[Order],
 f.LanguageID,
 f.ClientID,
 CAST(CASE WHEN d.NUM = 1 THEN f.Description ELSE NULL END AS NVARCHAR(2000)) [Description],
 CAST(CASE WHEN d.NUM = 2 THEN f.Description ELSE NULL END AS NVARCHAR(2000)) Disclaimer,
 Main.Other
FROM dbo.Main
CROSS JOIN dbo.DIM_NUMBERS d
JOIN dbo.Fact f
 ON (f.FactID = Main.DescriptionID AND d.NUM = 1) OR (f.FactID = Main.DisclaimerID AND d.NUM = 2)
JOIN dbo.Status s ON s.StatusID = f.StatusID;

CREATE UNIQUE CLUSTERED INDEX IDX_X_VIEW   
   ON dbo.X_VIEW  (ID, [Order], LanguageID, ClientID, [Description], Disclaimer, Other); 

我已重寫您的查詢以不使用 UNION ALL,但我沒有包含 GROUP BY,因為索引視圖中不允許使用 MIN 和 MAX。沒有任何聚合函式可以幫助您,因為您有一個 NVARCHAR 列。如果您有一個數字列,那麼您可能可以使用 SUM(COALESCE(COLUMN_NAME, 0)) 列來解決這個問題,但您不能將 SUM 聚合應用於 NVARCHAR。

我不會嘗試將查詢硬塞到索引視圖定義中,而是嘗試考慮其他解決方案。您可以將結果儲存在表格中嗎?根據描述列的長度,該列與索引視圖之間的空間差異可能不會那麼大。你能以某種有幫助的方式改變數據模型嗎?

引用自:https://dba.stackexchange.com/questions/157402