2009-08-08 74 views
1

對不起,我不確定如何使用該語句,而且我對SQL的使用並不太好。數據庫引擎是SQL Server Compact。我現在有這個疑問:SQL:爲每個唯一密鑰選擇最大值?

SELECT * 
FROM Samples 
WHERE FunctionId NOT IN 
(SELECT CalleeId FROM Callers) 
ORDER BY ThreadId, HitCount DESC 

這給了我:

ThreadId Function HitCount 
     1  164  6945 
     1  3817   1 
     4  1328  7053 

現在,我只想與線程的每個唯一值的最大的命中計數結果。換句話說,應該放棄第二行。我不知道如何解決這個問題。

[編輯]如果有幫助,這是同一個查詢的另一種形式:

SELECT * 
FROM Samples s1 
LEFT OUTER JOIN Callers c1 
    ON s1.ThreadId = c1.ThreadId AND s1.FunctionId = c1.CalleeId 
WHERE c1.ThreadId IS NULL 
ORDER BY ThreadId 

[編輯]我最終使架構更改,以避免這樣做,因爲建議的查詢者望而昂貴。感謝所有的幫助。

+0

是否有可能爲那裏是共享同一FunctionId 2個線程ID,對那些(ThreadId,FunctionId)在呼叫者,但不是其他?我問,因爲上面的兩個查詢沒有說同樣的事情。 – 2009-08-08 04:54:47

回答

2

SQL Server緊湊支持窗口函數嗎?

備選方案1 - 將包括所有打結的行。不包括行,如果給定線程的唯一行都有空的HitCount:

SELECT Thread, Function, HitCount 
FROM (SELECT Thread, Function, HitCount, 
     MAX(HitCount) over (PARTITION BY Thread) as MaxHitCount 
    FROM Samples 
    WHERE FunctionId NOT IN 
     (SELECT CalleeId FROM Callers)) t 
WHERE HitCount = MaxHitCount 
ORDER BY ThreadId, HitCount DESC 

方案2 - 將包括將所有行。如果沒有行,並與非空HitCount給定的線程,將返回所有行該線程:

SELECT Thread, Function, HitCount 
FROM (SELECT Thread, Function, HitCount, 
     RANK() over (PARTITION BY Thread ORDER BY HitCount DESC) as R 
    FROM Samples 
    WHERE FunctionId NOT IN 
     (SELECT CalleeId FROM Callers)) t 
WHERE R = 1 
ORDER BY ThreadId, HitCount DESC 

方案3 - 將非determistically挑領帶的情況下,一排並丟棄等。將包括行如果在一個線程中的所有行具有空HitCount

SELECT Thread, Function, HitCount 
FROM (SELECT Thread, Function, HitCount, 
     ROW_NUMBER() over (PARTITION BY Thread ORDER BY HitCount DESC) as R 
    FROM Samples 
    WHERE FunctionId NOT IN 
     (SELECT CalleeId FROM Callers)) t 
WHERE R = 1 
ORDER BY ThreadId, HitCount DESC 

替代4 & 5 - 使用舊的結構,如果窗口功能不可用,並說是什麼意思乾淨了一點比使用連接。基準如果spead是一個優先事項。兩者都返回參與平局的所有行。當非空值不適用於HitCount時,備選4將HitCount爲空。選項5不會返回HitCount爲空的行。

WITH maxHits AS(
    SELECT s.threadid, 
     MAX(s.hitcount) 'maxhits' 
    FROM SAMPLES s 
    JOIN CALLERS c ON c.threadid = s.threadid AND c.calleeid != s.functionid 
GROUP BY s.threadid 
) 
SELECT t.* 
    FROM SAMPLES t 
    JOIN CALLERS c ON c.threadid = t.threadid AND c.calleeid != t.functionid 
    JOIN maxHits mh ON mh.threadid = t.threadid AND mh.maxhits = t.hitcount 

任何數據庫的工作:

SELECT * 
FROM Samples s1 
WHERE FunctionId NOT IN 
    (SELECT CalleeId FROM Callers) 
AND NOT EXISTS 
    (SELECT * 
    FROM Samples s2 
    WHERE s1.FunctionId = s2.FunctionId 
    AND s1.HitCount < s2.HitCount) 
ORDER BY ThreadId, HitCount DESC 

SELECT * 
FROM Samples s1 
WHERE FunctionId NOT IN 
    (SELECT CalleeId FROM Callers) 
AND HitCount = 
    (SELECT MAX(HitCount) 
    FROM Samples s2 
    WHERE s1.FunctionId = s2.FunctionId) 
ORDER BY ThreadId, HitCount DESC 
2

這是我會怎麼做:

SELECT s1.* 
FROM Samples s1 
LEFT JOIN Samples s2 
    ON (s1.Thread = s2.Thread and s1.HitCount < s2.HitCount) 
WHERE s1.FunctionId NOT IN (SELECT CalleeId FROM Callers) 
    AND s2.Thread IS NULL 
ORDER BY s1.ThreadId, s1.HitCount DESC 

換句話說,該行s1對其中有沒有其他行s2匹配相同Thread而具有較大HitCount

+0

這裏有一個令人討厭的細微之處 - 嵌套子條款(SELECT CalleeId FROM Callers)也必須應用於連接的另一半。我重新調整了一下初始查詢: SELECT s1。* 的樣品S1 LEFT OUTER JOIN呼叫者C1 ON s1.ThreadId = c1.ThreadId AND s1.FunctionId = c1.CalleeId WHERE c1.ThreadId IS NULL – Promit 2009-08-08 01:02:24

1

將與SQL Server 2005+工作

SELECT t.* 
    FROM SAMPLES t 
    JOIN CALLERS c ON c.threadid = t.threadid AND c.calleeid != t.functionid 
    JOIN (SELECT s.threadid, 
       MAX(s.hitcount) 'maxhits' 
      FROM SAMPLES s 
      JOIN CALLERS c ON c.threadid = s.threadid AND c.calleeid != s.functionid 
     GROUP BY s.threadid) mh ON mh.threadid = t.threadid AND mh.maxhits = t.hitcount 
+0

如果(SELECT s.ThreadAID MAX(s.HitCount)從樣品中s GROUP BY s.ThreadId)返回一個最大值,它只屬於FunctionId在Callers.CallerId中的行嗎?這些行最終被刪除,並且來自FuctionId不在Callers.CallerId中的該行的Max(HitCount)被排除在結果之外。 – 2009-08-08 01:49:57

+0

好點。通過在CTE或內聯視圖中向CALLERS添加JOIN輕鬆進行更正 - 請參閱更新。 – 2009-08-08 01:58:21

+0

@rexem。注意到另一個問題:OP中沒有任何東西讓我相信調用者有一個ThreadId列。 – 2009-08-08 02:43:14