我之前问了这个问题,但错过了我问题的一个重要部分。
Return certain record based on criteria
获取此结果列表
Client | Date | YESorNO
-------------------------------
A1 | 01/01/2001 | NO
A1 | 01/01/2002 | NO
A1 | 01/01/2003 | YES
A1 | 01/01/2004 | NO
A1 | 01/01/2005 | NO
A1 | 01/01/2006 | NO
A1 | 01/01/2007 | YES
A1 | 01/01/2008 | YES
A1 | 01/01/2009 | YES
A2 | 01/01/2001 | NO
A2 | 01/01/2002 | NO
A2 | 01/01/2003 | YES
A2 | 01/01/2004 | NO
A2 | 01/01/2005 | YES
A2 | 01/01/2006 | YES
A3 | 01/01/2001 | NO
...etc...
该列表是按时间顺序排序的,除了降序/升序之外,我无法对其进行排序。
我无法排序是|否,找到First()或Last(),因为这不会给我所需的值。
我希望能够在每个客户的所有“未计算”之后返回第一个“是”。
在上面的Client [A1]示例中,第7行是我要返回的记录(2007年1月1日)。
客户[A2] - 第5行(01/01/2005)..等等
我的代码如下
var query =
(
from m in db.MyTable
where m.Criteria == XYZ
select new
{
Client = m.Client,
Date = m.Date,
YESorNO = m.YESorNO
}
).OrderBy(x => x.Date);
使用.FirstOrDefault(x => x.YesOrNO == "YES")
返回第3条记录。
User @RenéVogt建议
var result = query.AsEnumerable()
.TakeWhile(x => x.YESorNO == "YES")
.LastOrDefault();
会完成工作而且确实如此,但我忘了添加查询将返回许多客户端,我需要每个客户端的第一个“是”,因此上述代码是不够的。
迭代我的结果将耗费大量时间,虽然这是一个解决方案,我宁愿这个逻辑在数据库查询本身内(如果可能的话)
非常感谢
答案 0 :(得分:3)
您需要做的是按client
进行分组,然后从末尾开始查找每个的最后YES
。这样的事情(ClientList
是List<>
,您可能需要根据数据的位置进行更改):
var query = ClientList.OrderBy(x => x.client).ThenBy(x => x.date).GroupBy(x => x.client);
foreach (var client in query)
{
var lastYES=client.Reverse().TakeWhile(x => x.YESorNO == "YES")
.LastOrDefault();
Console.WriteLine(String.Format("{0} {1}",client.Key,lastYES.date));
}
//Output: A1 01/01/2007 0:00:00
// A2 01/01/2005 0:00:00
修改强>
Mansur Anorboev正确地建议按降序排序,因此无需Reverse
,因此代码将是:
var query = ClientList.OrderBy(x => x.client).ThenByDescending(x => x.date).GroupBy(x => x.client);
foreach (var client in query)
{
var lastYES=client.TakeWhile(x => x.YESorNO == "YES")
.LastOrDefault();
Console.WriteLine(String.Format("{0} {1}",client.Key,lastYES.date));
}
修改2
我仍然对我的解决方案不满意,因为它正在使用foreach。这可以在一个Linq命令中完成所有操作:
var query = ClientList.OrderBy(x => x.client)
.ThenByDescending(x => x.date)
.GroupBy(x => x.client, (key, g) => g.TakeWhile(x => x.YESorNO == "YES").LastOrDefault())
.ToList();
这将返回一个列表,其中每个客户端包含一个元素并且日期正确。
答案 1 :(得分:1)
我可以提供一点sql查询
;WITH cte AS (
SELECT *, ROW_NUMBER() OVER (ORDER BY Client DESC) AS rn
FROM [dbo].[tblSkaterhaz]
)
,gte AS (
SELECT Client,max(rn) mx FROM cte
WHERE YesOrNo = 'NO'
GROUP BY Client
)
SELECT cte.* FROM gte
INNER JOIN cte on cte.Client = gte.Client and cte.rn = gte.mx + 1
虽然它不是必需的解决方案,但它产生了所需的结果。您可以创建存储过程并在代码中使用它。
注意:这是根据上面提到的相同表格(和数据)进行测试的
我希望这会对你有所帮助。