2015-09-30 12 views
4

數據的隨機選擇我有一個這樣的表:算法做了求和一列與另一列

CREATE TABLE Table1 
    ([IdeaNr] int, [SubmitterName] varchar(4), [SubmitterDepartment] varchar(4)) 
; 

INSERT INTO Table1 
    ([IdeaNr], [SubmitterName], [SubmitterDepartment]) 
VALUES 
    (1, 'Joe', 'Org1'), 
    (1, 'Bill', 'Org2'), 
    (1, 'Kate', 'Org1'), 
    (1, 'Tom', 'Org3'), 
    (2, 'Sue', 'Org2'), 
    (3, 'Bill', 'Org2'), 
    (3, 'Fred', 'Org1'), 
    (4, 'Ted', 'Org3'), 
    (4, 'Kate', 'Org1'), 
    (4, 'Hank', 'Org3') 
; 

我想從查詢得到以下結果:

IdeaNr SubmitterCount SubmitterRndName SubmitterRndDepartment 
1  4    Joe or ...   Org1 (if Joe) 
2  1    Sue    Org2 
3  2    Bill or ...  Org2 (if Bill) 
4  3    Ted or ...   Org3 (if Ted) 

我已經嘗試了很多的事情都與自己種的JOIN表1中,派生表和GROUP BY,如:

SELECT COUNT(IdeaNr) AS SubmitterCount,IdeaNr,SubmitterName,SubmitterDepartment 
FROM Table1 
GROUP BY IdeaNr,SubmitterName,SubmitterDepartment 

我認爲問題在於創建一個算法,只需要第一個(或隨機)名稱和部門出現在一組IdeaNr中。很明顯,你可能會誤解這種數據的解釋,摹:

  • ORG1有2個想法
  • ORG2有1個想法,
  • Org3有1個想法,

但這種 「錯誤的平均」 的是任務的確定。你能幫我嗎?

編輯:預期的結果在討論過程中演變而來。期望的結果改爲:

IdeaNr SubmitterCount SubmitterRndName SubmitterRndDepartment 
1  4    Joe, Bill, ...  GroupIdea 
2  1    Sue    Org2 
3  2    Bill, Fred   GroupIdea 
4  3    Ted, ...   GroupIdea 
+0

我更正了預期結果中的第三行,因爲我認爲您輸錯了它。如果我做錯了,請進一步編輯它。 –

回答

3

試試這樣說:

DECLARE @Table1 TABLE ([IdeaNr] int, [SubmitterName] varchar(4), [SubmitterDepartment] varchar(4)); 
INSERT INTO @Table1([IdeaNr], [SubmitterName], [SubmitterDepartment]) 
VALUES 
    (1, 'Joe', 'Org1'), 
    (1, 'Bill', 'Org2'), 
    (1, 'Kate', 'Org1'), 
    (1, 'Tom', 'Org3'), 
    (2, 'Sue', 'Org2'), 
    (3, 'Bill', 'Org2'), 
    (3, 'Fred', 'Org1'), 
    (4, 'Ted', 'Org3'), 
    (4, 'Kate', 'Org1'), 
    (4, 'Hank', 'Org3'); 

SELECT x.IdeaNr 
     ,Count(x.IdeaNr) 
     ,MAX(Submitter.SubmitterName) AS SubmitterRndName 
     ,MAX(Submitter.SubmitterDepartment) AS SubmitterRndDepartment 
FROM @Table1 AS x 
CROSS APPLY 
(
    SELECT TOP 1 SubmitterName, SubmitterDepartment 
    FROM @Table1 AS y 
    WHERE y.IdeaNr=x.IdeaNr 
) AS Submitter 
GROUP BY x.IdeaNr 

還有一個想法,不知道如果你能需要的:

SELECT x.IdeaNr 
     ,Count(x.IdeaNr) 
     ,STUFF(
      (
      SELECT ', ' + y.SubmitterName --maybe with DISTINCT 
      FROM @Table1 AS y 
      WHERE y.IdeaNr=x.IdeaNr 
      FOR XML PATH('') 
      ),1,2,'') AS AllSubmitters 
     ,STUFF(
      (
      SELECT ', ' + z.SubmitterDepartment --maybe with DISTINCT 
      FROM @Table1 AS z 
      WHERE z.IdeaNr=x.IdeaNr 
      FOR XML PATH('') 
      ),1,2,'') AS AllDepartments 
FROM @Table1 AS x 
GROUP BY x.IdeaNr 

這都回到

IdeaNr     AllSubmitters    AllDepartments 
1   4   Joe, Bill, Kate, Tom  Org1, Org2, Org1, Org3 
2   1   Sue      Org2 
3   2   Bill, Fred     Org2, Org1 
4   3   Ted, Kate, Hank   Org3, Org1, Org3 

編輯:Followin摹你的想法從最後的評論:

SELECT x.IdeaNr 
     ,COUNT(x.IdeaNr) 
     ,STUFF(
      (
      SELECT DISTINCT ', ' + y.SubmitterName 
      FROM @Table1 AS y 
      WHERE y.IdeaNr=x.IdeaNr 
      FOR XML PATH('') 
      ),1,2,'') AS AllSubmitters 
     ,CASE WHEN COUNT(x.IdeaNr)=1 THEN (SELECT TOP 1 z.SubmitterDepartment FROM @Table1 AS z WHERE z.IdeaNr=x.IdeaNr) 
      ELSE 'GroupIdea' END AS Departments 
FROM @Table1 AS x 
GROUP BY x.IdeaNr 
+0

謝謝你的回答!你的兩個例子都很好。對於第一個程序:我從來沒有聽說過CROSS APPLY。我在這裏找到了一些解釋,比較JOIN和CROSS APPLY:http://explainextended.com/2009/07/16/inner-join-vs-cross-apply/ – Bebass

+0

@Bebass,很高興爲您提供幫助。 CROSS APPLY適用於基於行的訪問,特別是與XML和函數連接。一個提示:你可以很容易地改變第二種方法來「喬(Org1),比爾(Org2),凱特(Org1),湯姆(Org3)''等等。如果這是你所需要的,請投票和/或標記爲接受,thx! – Shnugo

+0

第二個程序對我來說是非常先進的)但是,將多行數據連接成單個字符串是一個很好的技巧!但是這個想法讓我想到了另一個想法:對於[AllDepartments]這一欄,只需要一個條目「GroupIdea」就可以了,而不是所有的部門名稱。這將有助於Excel中的進一步評估,因爲您只需在該列中添加一個元素,而不需要多次重新組合元素。 – Bebass

3

如果您想了解更多關於此主題搜索top-N-per-group。在SQL Server中,使用CROSS APPLY很容易。

SQL Fiddle

WITH 
CTE 
AS 
(
    SELECT 
     IdeaNr 
     ,COUNT(*) AS SubmitterCount 
    FROM @Table1 
    GROUP BY IdeaNr 
) 
SELECT 
    CTE.IdeaNr 
    ,CTE.SubmitterCount 
    ,CA.SubmitterName 
    ,CA.SubmitterDepartment 
FROM 
    CTE 
    CROSS APPLY 
    (
     SELECT TOP(1) 
      T.SubmitterName 
      ,T.SubmitterDepartment 
     FROM @Table1 AS T 
     WHERE T.IdeaNr = CTE.IdeaNr 

     --ORDER BY T.SubmitterName 
     --ORDER BY T.SubmitterDepartment 
     --ORDER BY CRYPT_GEN_RANDOM(4) 

    ) AS CA 
ORDER BY CTE.IdeaNr; 

如果你不把任何ORDER BYCROSS APPLY部分服務器將選擇一個「隨機」行。它不是隨機的,但是當您多次運行此查詢時,結果可能會相同或可能不同。實際上,如果您在表上創建或刪除索引,結果很可能會有所不同,但如果表很大,則每次運行查詢時結果可能會有所不同。

如果你想挑選一些特定行每個IdeaNr,那麼如果你想選擇一個真正的隨機行,然後ORDER BY CRYPT_GEN_RANDOM(4)使用ORDER BY名稱或部門或某些ID等

我得到沒有任何ORDER BY以下結果當我使用表變量本次測試沒有任何指標:

IdeaNr SubmitterCount SubmitterName SubmitterDepartment 
1   4     Joe    Org1 
2   1     Sue    Org2 
3   2     Bill    Org2 
4   3     Ted    Org3 

它看起來好像它的順序選擇了「第一」行每個IdeaNr,因爲他們被添加到表中。但是,不要被愚弄,沒有明確的ORDER BY的順序不能保證。如果您希望按照添加到表中的順序獲取每個IdeaNr的第一行,則需要以某種方式存儲有關此訂單的信息。例如,將一列ID int IDENTITY添加到表中,隨着新行的添加,表格會自動增加,然後您可以像這樣使用它ORDER BY ID DESC以獲得有保證的結果。

用SQL小提琴玩,看看它是如何工作的。

+0

非常感謝您的回答。我使用了很多SQLite,所以我一直在避免CTE。但在我看來,這是一個非常有用的概念。我在這裏找到了一些介紹:https://www.simple-talk.com/sql/t-sql-programming/sql-server-cte-basics/甚至SQLite似乎現在有它:http:// www .sqlite.org/lang_with.html – Bebass

+0

我也喜歡你的建議ORDER BY CRYPT_GEN_RANDOM(4)! – Bebass

+0

@Bebass,CTE使查詢更具可讀性。在這種情況下,可以將SELECT ... GROUP BY作爲嵌套查詢放入主查詢中。但是,它看起來像你的問題已經演變,你是在一個不同的結果後,所以這個答案變得沒有真正的相關性。 –