2012-08-25 107 views
2

考虑这个例子的数据:如何只选择在一列中具有唯一值的行?

field1 field2 
1  100 
2  100 
3  101 
4  102 
5  102 
6  103 

我想只选择记录,其中在field2值只出现一次。从上面的期望返回数据的一个例子是:

field1 field2 
3  101 
6  103 

这将如何与LINQ to SQL?

---编辑-------
大家好,非常感谢您的回复。我故意提供了简化的数据以便正确处理我的问题的根源。我认为所有这些答案都会根据我的示例数据返回所需的结果,我会将它们标记为所有答案。

但是在我的实际数据的情况下,使用的是什么我已经从你的回答了解到,我有这样的事情:

var RefinedSource = from a in dSource 
        group a by a.AssetID into g 
        where g.Count() == 1 
        select new 
        { 
          AssetID = g.Key, 
          AssetType = g.Min(a => a.AssetType), 
          IPInfo = AppUtility.GetIPInfo(g.Key), 
          Hostname = AppUtility.GetServerName(g.Key), 
          DeviceID = g.Min(a => a.DeviceID).ToString(), 
          Environment = AppUtility.GetSolutionAndEnvironmentNames(g.Key), 
          Manufacturer = g.Min(a => a.Manufacturer), 
          MakeModel = g.Min(a => a.MakeModel), 
          Location = g.Min(a => a.Location), 
          count = g.Count() 
        }; 

所以我很担心所有.min()调用...我推断这些是必要的,因为分组?有人可以解释为什么需要这些吗?在我的简单例子中,我没有看到它们是一个问题,但是使用我的真实数据,有多个对min()的调用只是为了能够包含我需要的所有字段数据......看起来并不像好。

该分组允许我测试我需要的条件(计数以识别重复值),但我如何更直接地使用这样的条件,但直接访问我真正的底层数据行?

例如,看看上面刚刚提供的示例,我希望能够使用原始“from a dSource”部分中的a.FieldName,但在引入后无法访问它“通过...分组”?

再次,感谢您的信息,我会标记为答案,但是如果任何人都可以解释所有调用min()(或max,或其他)的需要,我将不胜感激,也看到它看起来像我的真实数据,这仍然是我应该去的方式?

回答

1
from r in tables 
    group r.field2 by r.field1 into grp 
    where grp.Count() == 1 
    select new {grp.First(), grp.Key} 

我会仔细检查,这确实一个SQL调用。它应该,如果是的话,我会保持它在这里,因为First是一种非常常用的Linq方法,并且当在给定情况下有几十个同样好的东西时,应该倾向于熟悉。如果它确实导致多个SQL调用(再次,我会感到惊讶),然后尝试Max()Min()而不是First()

1

这里是如何,将在SQL(有时是更快地使用SQL)来完成:

SELECT max(field1), field2 
FROM table 
GROUP BY field2 
HAVING count(field2) = 1 

使用窗函数在SQL Server实例
(注意,不能测试,现在的OVER条款可能需要在哪里):

SELECT COUNT() OVER(PARTITION BY field2) AS [field2Count], * 
FROM table 
WHERE [field2Count] = 1 
+0

嗨霍根,感谢信息。我想坚持LINQ到SQL,因为我的整个应用程序正在使用,我想保持一致。但我很好奇,如果表格中还有field3,field4和field5,并且需要在结果中包含所有字段?那将是什么样子?你是否被迫在每个领域使用聚合函数来包含它们? – c0pe

+0

它取决于SQL的版本。如果我们正在谈论SQL Server,那么最新版本允许使用“窗口函数”。这个特性在Oracle和一些progre,mysql等版本中也是可用的。我需要更多的细节来回答这个问题 - 我给出的答案是标准SQL,因此平台/版本无关紧要。 (在标准的SQL中,你可以使用聚合函数来解决这个问题 - 它可能会或可能不如窗口函数那么快。) – Hogan

+0

我已经添加了在SQL Server中使用OVER子句的标准示例。 – Hogan

0

随着LINQ,你可以简单地做:

var groups = list.GroupBy(r => r.Value).Where(grp => grp.Count() == 1); 

foreach(var gr in groups){ 
    var field1 = gr.Key;  // KEY: is your FIELD1 
    var field2 = gr.Value; // VALUE: is your FIELD2 
} 
+0

您确定没有使用聚合方法的分组会导致对每个项目单独调用数据库的问题吗?我现在无法检查,但我不确定引擎会意识到,因为每个密钥只有一个值,所以它可以进行单个呼叫。 –

+0

@JonHanna:现在我手上没有工具来检查,但我认为它可以通过'linq-to-sql'进行管理。 – Tigran

+0

它绝对不能总是,因为我有时发现在不合时宜的时候! –

相关问题