2015-10-04 37 views
3

我想提供一個真正的數據倉庫模式的簡單示例,所以請原諒我,如果表是如此天真和基本。在MS SQL Server中的所有選擇字段上分組的更好方法

主表被稱爲ItemsItemName作爲主鍵:

Items Table

有兩種稱爲Propertiesattributes所有其它表與id柱(自動身份)作爲主鍵:

Attributes

Properties

問題:我想查詢這些表是這樣的:

SELECT 
    I.ItemName, A.AttributeName, I.Col1, I.Col2, I.Col3, I.Col4, 
    pForFilter.Property 
FROM 
    Items I 
LEFT OUTER JOIN 
    attributes A ON I.ItemName = A.ItemName 
LEFT OUTER JOIN 
    Properties pForFilter On I.ItemName = pForFilter.ItemName 
GROUP BY 
    I.ItemName, A.AttributeName, I.Col1, I.Col2, I.Col3, I.Col4, 
    pForFilter.Property 
HAVING 
    pForFilter.Property = 'Prop1' 

下面是結果:

Results

查詢的實部爲I.ItemnameA.AttributeName爲不同的值,因此添加GROUP BY以模擬這兩個字段上的不同值。請注意,過濾是根據Property列完成的,但我不需要選擇列表中的屬性。然而,我還需要選擇列表中的其他字段Items表(Col1,Col2,Col3,Col4)。我的問題是我可以重寫這個查詢,這樣我就不必在所有這些額外的字段上分組了嗎?提供的查詢是否有效?如果我必須使用它,我可以使用索引來提高查詢的速度以及它可以是什麼索引?

回答

1

從我的查詢邏輯中得到的結果,你只對'Prop1'感興趣,所以你可以內部加入。所以,假設你的商品表沒有重複,那麼你只需要得到不同的ItemName,AttributeName組合。像這樣的查詢會給你你在group by

SELECT I.ItemName, attr.AttributeName, I.Col1, 
     I.Col1, I.Col2, I.Col3, I.Col4, prop.Property 
FROM Items I 
    INNER JOIN (SELECT p.ItemName, p.Property 
       FROM Properties p 
       WHERE p.Property = 'Prop1' 
       GROUP BY p.ItemName, p.Property) prop 
      ON I.ItemName = prop.ItemName 
    LEFT JOIN (SELECT A.ItemName, A.AttributeName 
       FROM Attributes A 
       GROUP BY A.ItemName, A.AttributeName) attr 
      ON I.ItemName = attr.ItemName 
+0

內蒙古組合JOIN和GROUP BY必填字段的是我錯過了。我可以使用索引提高速度嗎?特殊項目表具有良好的記錄數量,屬性可以達到1000行(可以忽略),屬性表可以達到100萬行。 –

+0

@YasserSobhdel,我沒有索引完美的知識。但我認爲在連接列上創建非聚集索引可能會提高性能。看到這篇文章建議索引http://www.sqlskills.com/blogs/kimberly/indexes-just-because-you-can-doesnt-mean-you-should/ – BICube

1

它看起來就像你不需要什麼GROUP需要這麼多列的內容。

首先,你要找到有房產Prop1所有項目:

SELECT Properties.ItemName 
FROM Properties 
WHERE Properties.Property = 'Prop1' 

它沒有意義的,我允許兩排,在這個表中的同ItemNameProperty,所以你應該添加這對列的唯一約束使您的意圖對程序員和查詢優化器變得清晰。有了這個約束,這裏不需要GROUP BY

既然您要過濾Property,我會在此表中添加以下唯一索引。它會執行約束並幫助搜索。索引中列的順序非常重要。

CREATE UNIQUE NONCLUSTERED INDEX [IX_Properties] ON [dbo].[Properties] 
(
    [Property] ASC, 
    [ItemName] ASC 
)) 

事實上,我會考慮取消從該表ID列,使該唯一索引主鍵,尤其是如果這ID沒有在國外很多鍵使用。它也可能是有用的(對於其他可能的查詢)爲這個表添加第二個唯一索引,並且這兩列以另一個順序列出。

類似的想法適用於Attributes表。一旦您明確指出,在Attributes表中只能有一行與ItemNameAttributeName相同,則不需要GROUP BY

您的查詢就會變成:

SELECT 
    I.ItemName 
    ,Attributes.AttributeName 
    ,I.Col1 
    ,I.Col2 
    ,I.Col3 
    ,I.Col4 
FROM 
    Items AS I 
    INNER JOIN Properties ON Properties.ItemName = I.ItemName 
    INNER JOIN Attributes ON Attributes.ItemName = I.ItemName 
WHERE 
    Properties.Property = 'Prop1' 
; 
+0

感謝您的答案,但數據結構倉庫是預先確定的,我必須查詢一些視圖。這些視圖是具有相同名稱並附加月份名稱的表的並集(即SomeView_Jan,SomeView_Feb,...) –

相關問題