2012-03-27 81 views
4

如何篩選僅符合某些標準的組與其他組相比較的組的結果集?例如,只有那些組織記錄數量最多的組織?比較SQL組和海誓山盟

我原本以爲子查詢如下應該做的伎倆:

SELECT * FROM (
    SELECT *, COUNT(*) AS Records 
    FROM  T 
    GROUP BY X 
) t HAVING Records = MAX(Records); 

然而,除了在一個空的記錄最終HAVING條款的結果......這是怎麼回事?

+1

如果的Juho的回答不會給你你需要什麼,請輸入您的數據庫類型使用(oracle,mysql,sql server等)(通過使用標籤,你把sql放在哪裏。如果你只需要通用的SQL解決方案,請在消息正文中提及)。如果您已花時間在您的文章和sqlfiddle.com中添加一些示例數據和表格結構,您可以更輕鬆地讓人們更深入地查看您的問題。 – 2012-03-27 13:41:20

+1

@LevinMagruder:MySQL 5.1;示例數據http://sqlfiddle.com/#!3/b4306/4 – eggyal 2012-03-27 13:49:08

+0

好吧,我不使用mysql,但有人會告訴你一個比我在下面顯示的更簡單的查詢,將他們的答案標記爲答案,但是如果我的回答很有幫助,而且你想向我發射upvote,謝謝。如果你有很多像這樣的問題,也許還會閱讀標籤爲「每個組最多的問題」的問題,那麼有很多有趣的方法。 – 2012-03-27 14:00:00

回答

1

對於你給出的確切問題,一種看待它的方法是你想要一組記錄,其中沒有其他組具有更多記錄。所以,如果你說

SELECT taxid, COUNT(*) as howMany 
GROUP by taxid 

你得到所有縣及其計數

然後你就可以把這個表達式,通過使其子查詢表,並給它一個別名。在下面,我將查詢的兩個「副本」分配給名稱X和Y,並要求在一張表中沒有更多的taxids。如果有兩個相同的號碼,我會得到兩個或更多。不同的數據庫具有專有語法,特別是TOP和LIMIT,這使得這種查詢變得更簡單,更易於理解。

SELECT taxid FROM 
(select taxid, count(*) as HowMany from flats 
GROUP by taxid) as X 

WHERE NOT EXISTS 
(
SELECT * from 
(
    SELECT taxid, count(*) as HowMany FROM 
    flats 
    GROUP by taxid 
    ) AS Y 
    WHERE Y.howmany > X.howmany 
) 
+0

我知道,通過在'WHERE'子句中重複子查詢,我可以提取最大行數(只需使用'max()'就可以正常工作),但是調用相同子查詢倍;有沒有什麼辦法可以引用WHERE子句中'FROM'子句中子查詢產生的臨時表? – eggyal 2012-03-27 14:00:57

0

試試這個:

SELECT * FROM (
    SELECT *, MAX(Records) as max_records FROM (
    SELECT *, COUNT(*) AS Records 
    FROM T 
    GROUP BY X 
) t 
) WHERE Records = max_records 

我很抱歉,我現在不能測試此查詢的有效性。

+0

第二級查詢中的「SELECT MAX(記錄)」會將記錄集截斷爲只有一個記錄,其中「記錄」和「max_records」字段不一定相同(因此總體結果將只包含零或一個記錄);也許這是我的原始查詢所暗示的,因此沒有結果? – eggyal 2012-03-27 13:43:21

4

在MySQL(我假設你正在使用,因爲你已經張貼SELECT *, COUNT(*) FROM T GROUP BY X這將在我所知道的所有RDBMS失敗)。您可以使用:

SELECT T.* 
FROM T 
     INNER JOIN 
     ( SELECT X, COUNT(*) AS Records 
      FROM T 
      GROUP BY X 
      ORDER BY Records DESC 
      LIMIT 1 
     ) T2 
      ON T2.X = T.X 

這在MySQL進行了測試,並刪除隱式分組/聚集。

如果你可以使用窗口功能,並與領帶或公用表表達式TOP/LIMIT的一個變得更短:

窗口函數+ CTE:(MS SQL-服務器& PostgreSQL的測試)

WITH CTE AS 
( SELECT *, COUNT(*) OVER(PARTITION BY X) AS Records 
    FROM T 
) 
SELECT * 
FROM CTE 
WHERE Records = (SELECT MAX(Records) FROM CTE) 

窗口函數與TOP(測試MS SQL服務器)

SELECT TOP 1 WITH TIES * 
FROM ( SELECT *, COUNT(*) OVER(PARTITION BY X) [Records] 
      FROM T 
     ) 
ORDER BY Records DESC 

最後,我從來沒有使用甲骨文所以apolgies沒有添加一個解決方案,在oracle上工作...


編輯

我的解決方案對於MySQL並沒有考慮到的關係,和我的一個解決這種對腳趾的步驟建議你所說的你想避免(副本子查詢),所以我不知道我能幫助畢竟,但是隻是在情況下,優選這裏是你的提琴要求,將工作的一個版本:

SELECT T.* 
FROM T 
     INNER JOIN 
     ( SELECT X 
      FROM T 
      GROUP BY X 
      HAVING COUNT(*) = 
        ( SELECT COUNT(*) AS Records 
         FROM T 
         GROUP BY X 
         ORDER BY Records DESC 
         LIMIT 1 
        ) 
     ) T2 
      ON T2.X = T.X 
+0

第一個(mysql)的確會失去聯繫;這可能是eggyal想要的,如果不是的話,我認爲你必須將它改寫成與count相匹配。後兩者不會失去聯繫。 – 2012-03-27 14:27:09

+0

@LevinMagruder是的,幾分鐘前注意到了這一點,添加了一個編輯,但現在我也不認爲這是OP所要的,因爲它重複了子查詢,但據我所知,這是不可避免的。 – GarethD 2012-03-27 14:30:29

+0

+1比我的「不存在」邏輯更直接。 – 2012-03-27 14:31:36