2016-11-30 52 views
1

我有一個情況我有:從事實數據表中提取行具有丟失的數據,使用元數據表

  1. 與ID列這是不是唯一的,但是不能爲null事實表。這一事實也有很多其它的尺寸(列),其可以是具有默認值-1的(在邏輯上是指爲null) 實施例:

    id | Dimension1 | Dimension2 | Dimension3 
    1   Value   -1   Value 
    1   -1   -1   Value 
    2   -1   Value   Value 
    
  2. 具有相同的尺寸的事實表元數據表。該表中的每一行表示事實表中的唯一標識。其餘的列用null或1填充,其中1表示此維度是此ID的事實表中的必需維度。 例子:

    id | Dimension1 | Dimension2 | Dimension3 
    1   1       1 
    2       1    1 
    

我的目標是讓只從根據元數據表缺少必需的信息的事實表中的行。所以從上面的例子中,我只會得到id = 1的行,其中Dimension1 = -1,因爲元數據表對於id = 1表示,因此維1和維3是必需的。

是否有這樣做的一個簡單的方法?

我做了一個非常複雜的查詢,其中有各個方面之間的這兩個表和的情況下,檢查之間的連接(我有超過100人)。然後,這些檢查指定-1,如果維度缺失實際上卻是必需的,並且有將這些歸納爲所有行和只挑選了負和行外部查詢。 它不工作到100%,我認爲它太複雜,一條真正的大事實表運行,所以我接受的想法。

編輯:動態SQL不允許:(

回答

1

我會建議使用熱膨脹係數和不同的查詢......在這個解決方案中,您將需要添加案件很好,但加入,他們似乎更簡單,我和你並不需要總結的任何虛擬值...

DECLARE @t TABLE(
id int, Dimension1 int, Dimension2 int, Dimension3 int 
) 

DECLARE @tMeta TABLE(
id int, Dimension1 int, Dimension2 int, Dimension3 int 
) 

INSERT INTO @t VALUES (1, 123, -1, 345), (1, -1, -1, 246), (2, -1, 567, 987) 
INSERT INTO @tMeta VALUES (1, 1, NULL, 1), (2, NULL, 1, 1) 

;WITH cte AS(
SELECT id, 
     CASE WHEN Dimension1 = -1 THEN NULL ELSE 1 END Dimension1, 
     CASE WHEN Dimension2 = -1 THEN NULL ELSE 1 END Dimension2, 
     CASE WHEN Dimension3 = -1 THEN NULL ELSE 1 END Dimension3 
    FROM @t 
EXCEPT 
SELECT * 
    FROM @tMeta 
EXCEPT 
SELECT id, ISNULL(Dimension1,1), ISNULL(Dimension2,1), ISNULL(Dimension3,1) 
    FROM @tMeta 
) 
SELECT t.* 
    FROM @t t 
    JOIN cte c ON t.id = c.id 
      AND CASE WHEN t.Dimension1 = -1 THEN -1 ELSE 1 END = ISNULL(c.Dimension1, -1) 
      AND CASE WHEN t.Dimension2 = -1 THEN -1 ELSE 1 END = ISNULL(c.Dimension2, -1) 
      AND CASE WHEN t.Dimension3 = -1 THEN -1 ELSE 1 END = ISNULL(c.Dimension3, -1) 
+0

謝謝,我卻注意到,在情況下,實際上行有各個方面(或多個指定尺寸比需要的)它仍然會被拾取,因爲它不會被EXECPT部分刪除,因爲這個維度組合在元數據中不存在。我試圖解決這個問題,並陷入:( –

+0

嘿,對不起,我忘了這部分。我會建議添加第二個除了部分:除 選擇ID,ISNULL(Dimension1,1),ISNULL(Dimension2,1),ISNULL (Dimension3,1) FROM @tMeta 至少在我小的測試看起來OK和行所有的/不顯示了更多的維度。 – Tyron78

0

您可以使用UNPIVOT簡化查詢也不必ROWID在事實表,以便第一CTE使ROW_NUMBER()的工作方式的RowId 。事實表然後,我們讓非透視表(事實和模板表),並加入他們的行列:

WITH TFBase AS 
(
    SELECT TF.*, ROW_NUMBER() OVER (ORDER BY ID) as TableRowID FROM TF 

), 
TFU AS 
(
    select id,TableRowID,dim,val 
    from TFBase 
    unpivot 
    (
    val for dim in (Dimension1, Dimension2, Dimension3) 
) u 
    WHERE U.Val <>-1 
) 
, 
TFT AS 
(
    select id,dim,val 
    from TTemplate 
    unpivot 
    (
    val for dim in (Dimension1, Dimension2, Dimension3) 
) u 
    WHERE Val is NOT NULL 
) 

SELECT * FROM TFBase WHERE 
TableRowID IN 
(
    SELECT TableRowID FROM TFU 
    LEFT JOIN TFT ON 
     (TFU.id=TFT.id) AND (TFU.dim = TFT.dim) 
    GROUP BY TableRowID, TFU.ID 
    HAVING COUNT(TFT.Val) <> (SELECT COUNT(*) FROM TFT WHERE ID = TFU.ID) 
) 
+0

感謝您的幫助,我認爲,爲了通過在事實表是一個非常耗時的操作,但... –