Как я могу удалить Дубликат "ПОЧТИ", используя LINQ? (ИЛИ SQL?) - PullRequest
2 голосов
/ 01 апреля 2010

Это должно быть легко для гуру LINQ.

Я делаю сложный запрос, используя UNIONS и CONTAINSTABLE в моей базе данных, чтобы вернуть ранжированные результаты в мое приложение.

Я получаю дубликаты в моих возвращенных данных. Это ожидается. Я использую CONTAINSTABLE и CONTAINS, чтобы получить все нужные мне результаты. CONTAINSTABLE ранжируется по SQL, а CONTAINS (который запускается только в поле Ключевые слова) - это мой жесткий код. (Извините, если это не имеет смысла)

В любом случае, поскольку кортежи не идентичны (их ранг различен), возвращается дубликат.

Я считаю, что лучший способ справиться с этим - использовать LINQ.

Я знаю, что буду использовать метод расширения Distinct(), но должен ли я реализовать интерфейс IEqualityComparer? Мне немного неясно, как это сделать.

Ради аргумента, скажем, мой набор результатов структурирован следующим образом:

class Content {
  ContentID int //KEY
  Rank int 
  Description String 
}

Если у меня есть List<Content>, как бы я написал метод Distinct() для исключения Rank? В идеале я хотел бы сохранить самый высокий рейтинг контента. Итак, если у одного Контента RAnk 112, а у другого 76. Я бы хотел сохранить рейтинг 112.

Надеюсь, я дал достаточно информации.

EDIT

Вот пример SQL для тех, у кого есть идея, как это сделать в SQL:

UNION ALL  
SELECT
    p.ProductID     AS ContentID
  , p.ProductName   AS Title
  , K.RANK          AS Rank
  , 'Product'       AS ContentType
  , p.AddedDateTime

FROM Products AS p
 INNER JOIN CONTAINSTABLE(NaturalFactorsPIM.dbo.Products,*, @SearchPred, @TopN) AS K ON K.[KEY] = P.ProductID
WHERE @IncludeProducts = 1 
  AND p.ProductStatus = 1 

UNION ALL  
SELECT
   p.ProductID    AS ContentID
 , p.ProductName  AS Title
 , 80             AS Rank
 , 'Product'      AS ContentType
 , p.AddedDateTime

FROM Products AS p
WHERE FREETEXT( p.ProductKeywords, @SearchPred)
  AND @IncludeProducts = 1 
  AND p.ProductStatus = 1 

ORDER BY Rank DESC

Ответы [ 2 ]

1 голос
/ 01 апреля 2010

Это должно делать то, что вы хотите:

Var List<Content> AllTheData = GetTheDataForThisExample()
Var DistinctDataWithMaxRank = From C in AllTheData
    Group C by C.ContentID, C.Description
         Into G
    Select New { ContentID = g.ContentID
                 Rank = (From rmax in g select rmax.rank).Max()
                 Description = g.Description
               };

Но, если я вас правильно понимаю, в SQL это будет очень просто:

Select ContentID, Max(Rank) As Rank, Description
From (Select * From ComplicatedFullTextSearchQuery()) As Q
Group By ContentID, Description

Я организовал этот sql так, будто ваш основной запрос был UDF; каким бы ни был ваш исходный запрос, поместите его в () во второй строке. Если производительность имеет значение, попросите процедуру / функцию поместить исходный запрос во временную таблицу, а затем просто выполните:

Select ContentID, Max(Rank) As Rank, Description
From TempTable    Group By ContentID, Description
0 голосов
/ 01 апреля 2010

Группировка по ContentID, затем OrderBy Rank и выбор первого элемента из каждой полученной группы:

var result = myContent.GroupBy( c => c.ContentID, 
                                g => g.OrderBy( x => x.Rank ).First() );

Использование синтаксиса понимания запросов:

var result = from c in myContent
             group c by c.ContentID into g
             select g.First() order by g.Rank;
...