2011-10-18 38 views
0

我有以下數據一個非常簡單的MS SQL表(含列名和數據類型):一個簡單而複雜的SQL查詢

TableId  PersonName    Attribute   AttributeValue 
(int)  (nvarchar 50)   (nvarchar 50)  (bit) 
----------- ----------------------- ------------------- -------------- 
1   A      IsHuman    1 
2   A      CanSpeak   1 
3   A      CanSee    1 
4   A      CanWalk    0 
5   B      IsHuman    1 
6   B      CanSpeak   1 
7   B      CanSee    0 
8   B      CanWalk    0 
9   C      IsHuman    0 
10   C      CanSpeak   1 
11   C      CanSee    1 
12   C      CanWalk    0 

現在,我需要的結果是什麼獨特PERSONNAME有這兩個屬性IsHuman和CanSpeak用的AttributeValue = 1

預期的結果應該是(不能包括C作爲這其中有IsHuman = 0)

PersonName 
------------ 
A 
B 

可以請哪位高手幫我一個書面方式SQL查詢爲此。

+1

@suresh你發佈你的答案在這裏,我也格式化該問題,它的外觀好,那麼爲什麼你改變了所有這一連接 – rahularyansharma

回答

2
SELECT PersonName 
FROM MyTable 
WHERE (AttributeName = 'IsHuman' AND AttributeValue = 1) OR 
     (AttributeName = 'CanSpeak' AND AttributeValue = 1) 
GROUP BY PersonName 
HAVING COUNT(*) > 1 

SELECT PersonName 
FROM MyTable 
WHERE AttributeValue = 1 AND AttributeName IN ('IsHuman', 'CanSpeak') 
GROUP BY PersonName 
HAVING COUNT(*) > 1 
+0

好編輯列文。我更喜歡你的版本 –

+0

它應該有與原始版本完全相同的執行計劃,但我覺得它更具可讀性。 +1順便說一句你的解決方案。 –

+0

嗨迪倫史密斯,感謝您的及時回覆。我們可以在「CanSee」,「CanWalk」等條款中添加更多內容。根據用戶選擇。它可能會根據選擇而有所不同。 –

0
select personname from yourtablename where personname in ('a','b') group by personname 
+2

它給出了預期的結果... :) – cairnz

+0

如果還有d呢? – rahularyansharma

+0

@rahularyansharma改變 – Rajkumar

1
SELECT PersonName FROM MyTable 
WHERE PersonName IN 
(SELECT T1.PersonName FROM MyTable T1 WHERE T1.Attribute = 'IsHuman' and T1.AttributeValue='1') 
AND (Attribute = 'CanSpeak' AND AttributeValue='1') 
+0

這隻會因爲我使用了錯誤的AttributeValue類型而無法使用。我看不到另一個問題。請解釋一下。 –

+0

我錯過了你的IN語句的左括號,並且認爲CanSpeak子句與IsHuman子句進行了AND運算。我會刪除我的評論並且贊成這個答案,但是您可能會考慮重新設置語句的格式,以使AND顯然不是IN語句的一部分。 –

-1

我實際上將此作爲面試的篩選問題。沒有人會獲得這份工作。好的,也許你會的,但是當你使用的策略可能或不可行時,它們不是普遍化的,它們錯過了關係代數的基本概念,即機智,別名。

正確的答案(在這個意義上,它會讓我更容易僱用你,還有同樣重要的感測到關係數據庫管理系統的優化理解它,它可以擴展到其他任意複雜,案件)是

SELECT t1.PersonName 
    FROM MyTable t1, MyTable t2 
WHERE t2.AttributeName = 'CanSpeak' 
     AND t2.AttributeValue = 1 
     AND t1.AttributeName = 'IsHuman' 
     AND t1.AttributeValue = 1 
     AND t1.PersonName = t2.PersonName; 
+1

該聲明包含錯誤,使用反模式並且執行比提議的解決方案更差。你應該解僱任何人提出這個(不是我downvote btw) –

+0

可以通過添加一個新的表格表達式每行搜索條件,這是不實際的。雖然我同意它可以擴展到任意複雜的情況,但實現起來並不容易。這樣做的「正確」方式是使用圖像關係。在SQL中,我們可以得到的最好的是關係分解。請記住,在** SQL **中,工作單元是行(不是表):在這種情況下擴展的方式是將條件行添加到除數表,並使用相同的查詢。你的建議基本上是動態SQL。 – onedaywhen

+0

順便說一句,你稱之爲「別名」的關係重命名操作符(和SQL標準稱爲「關聯名稱」)不構成我知道的任何關係代數的一部分。當然,這對代數是有用的,但不夠關鍵。達爾文的代數包括屬性重命名但不包含關係重命名。事實上,Darwen特別批評SQL迫使人們不必要地將相關名稱應用於表格。 [Citation](http://www.dcs.warwick.ac.uk/~hugh/TTM/Importance-of-Column-Names.pdf):第9頁,「TEETH_GNASHER」。 – onedaywhen

0

我認爲根據索引和表格大小,兩個內部連接可能會給您帶來好的性能。

SELECT t.PersonName FROM table t 
INNER JOIN table t2 ON t.PersonName=t2.PersonName AND t3.Attribute = 'IsHuman' AND t2.AttributeValue = 1 
INNER JOIN table t3 ON t2.PersonName=t3.PersonName AND t3.Attribute = 'CanSpeak' AND t3.AttributeValue = 1 

SELECT t.PersonName FROM table t 
INNER JOIN table t2 ON t.PersonName=t2.PersonName 
INNER JOIN table t3 ON t2.PersonName=t3.PersonName 
WHERE t2.Attribute = 'IsHuman' AND t2.AttributeValue = 1 AND t3.Attribute = 'CanSpeak' AND t3.AttributeValue = 1 

該溶液可以顯著然而簡化應的屬性IsHuman和CanSpeak剛與它們之間的連接ID的表不同的表。聽起來像這張表可能會受益於一些正常化。

如果你無法取得進展,視圖可能有助於表現。我在家裏沒有安裝SQL,所以我無法驗證任何性能方面。