2012-03-28 52 views
2

我有一個設置,看起來像這樣:集團通過該鏈條上來回兩個領域

CREATE TABLE MessageGrouping(MessageGroupingId bigint IDENTITY(1,1), 
          StoredMessageId bigint, MessageGroupId bigint) 

INSERT INTO [MessageGrouping]([StoredMessageId], [MessageGroupId]) 
SELECT 1, 301 UNION ALL 
SELECT 1, 302 UNION ALL 
SELECT 2, 302 UNION ALL 
SELECT 3, 303 UNION ALL 
SELECT 4, 304 UNION ALL 
SELECT 2, 305 UNION ALL 
SELECT 6, 305 UNION ALL 
SELECT 7, 303 
GO 

我需要這個返回含量(StoredMessageId S)是這樣的:

[1,2,6], [3, 7], [4] 

更新:第一組的邏輯是這樣的:StoredMessageId 1有MessageGroupId 301和302就可以了。但MessageGroupId 302也有StoredMessageId 2。所以StoredMessageId 2必須包含在組中。

StoredMessageId 2也有MessageGroupId 305在上面。並且MessageGroupId 305有StoredMessageId 6,所以它也包含在該組中。

我在LinqPad上試了一下,空了。一個簡單的MessageGroupings.GroupBy(x=>x.MessageGroupId)只按MessageGroupId(如預期的)分組。

添加在StoredMessageId S(MessageGroupings.GroupBy(x=>new {x.MessageGroupId, x.StoredMessageId})只是把每排在自己的組。

有沒有辦法做鏈接分組Linq中像我期待的?我也是細做它的SQL。

我希望能夠在微ORM使用這個像Dapper,但如果我需要實體框架,我可以做到這一點

+0

我真的不明白的組是如何做出 – 2012-03-28 22:20:35

+0

如何編寫SQL語句得到的結果? – 2012-03-28 22:21:19

+1

@AdrianIftode - 我更新了我的問題,以解釋這些組是如何製作的。至於如何在SQL中寫這個,我也畫了一個空白。我希望能夠認識Linq或SQL的人能幫助我。正如我在我的問題中指出的,我很滿意Linq或SQL中的答案。 (這不是一個「將此SQL轉換爲Linq」的問題。) – Vaccano 2012-03-28 22:40:48

回答

3

好了 - 違背了我的想法,你可以做到這一點與一個遞歸的CTE。
不是很漂亮......

請注意,所有的測試都是在DB2上完成的,它沒有辦法在行內返回數組。我不知道SQL Server是否可以(所以你可能需要解析結果)。我做不是建議試圖用Linq做到這一點 - 如果有的話,這應該直接在數據庫上運行。

WITH Mappings(beginId, storedId, groupId, storedPath, groupPath) as (
    SELECT a.StoredMessageId, a.StoredMessageId, a.MessageGroupId, 
      a.StoredMessageId + "|", a.MessageGroupId + "|" 
    FROM MessageGrouping as a 
    WHERE NOT EXISTS (SELECT 1 
         FROM MessageGrouping as b 
         WHERE b.StoredMessageId < a.StoredMessageId 
         AND b.MessageGroupId = a.MessageGroupId) 
    AND NOT EXISTS (SELECT 1 
        FROM MessageGrouping as b 
        WHERE b.MessageGroupId < a.MessageGroupId 
        AND b.StoredMessageId = a.StoredMessageId) 
    UNION ALL 
    SELECT a.beginId, a.storedId, b.MessageGroupId, 
      a.storedPath, a.groupPath + b.MessageGroupId + "|" 
    FROM Mappings as a 
    JOIN MessageGrouping as b 
    ON b.StoredMessageId = a.storedId 
    AND b.MessageGroupId <> a.groupId 
    AND a.groupPath NOT LIKE "%" + b.MessageGroupId + "%" 
    UNION ALL 
    SELECT a.beginId, a.StoredMessageId, a.groupId, 
      a.storedPath + b.StoredMessageId + "|", a.groupPath 
    FROM Mappings as a 
    JOIN MessageGrouping as b 
    ON b.MessageGroupId = a.groupId 
    AND b.StoredMessageId <> a.storedId 
    AND a.storedPath NOT LIKE "%" + b.StoredMessageId + "%"), 

    Result_Rows (ids, num) as (
    SELECT storedPath, 
      ROW_NUMBER() OVER(PARTITION BY beginId 
           ORDER BY LENGTH(storedPath) DESC) 
    FROM Mappings) 
SELECT ids 
FROM Result_Rows 
WHERE num = 1 

產量ids

1|2|6| 
3|7| 
4|         
+0

看起來很有趣。我會明天在我的sql服務器上嘗試它。感謝你的回答! – Vaccano 2012-03-29 01:03:53