Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/70.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 根据条件返回特定记录(2)_C#_Sql_Linq - Fatal编程技术网

C# 根据条件返回特定记录(2)

C# 根据条件返回特定记录(2),c#,sql,linq,C#,Sql,Linq,我以前问过这个问题,但遗漏了问题的一个关键部分 以这个结果列表为例 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

我以前问过这个问题,但遗漏了问题的一个关键部分

以这个结果列表为例

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...
列表是按时间顺序排列的,我不能排序,这是降序/升序以外的任何其他方式

我无法对Yes | NO进行排序并找到第一个()或最后一个(),因为这不会给我所需的值

我希望能够在每个客户的所有“否”都计算完毕后返回第一个“是”。

在上面的客户机[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”)
返回第三条记录

用户@RenéVogt建议

var result = query.AsEnumerable()
                  .TakeWhile(x => x.YESorNO == "YES")
                  .LastOrDefault();
将完成任务,但我忘了添加查询将返回多个客户机,并且我需要每个客户机的第一个“是”,因此上面的代码不够

迭代我的结果将非常耗时,虽然这是一个解决方案,但我更希望这种逻辑在数据库查询本身中(如果可能的话)


非常感谢

您需要做的是按
客户端进行分组
,然后从末尾开始查找每个的最后一个
是。类似于此(
ClientList
是一个
列表
,您可能需要根据数据的位置对其进行更改):

编辑

曼苏尔·阿诺博耶夫(Mansur Anorboev)正确地建议按降序日期进行订购,从而消除了反向订购的需要,因此代码为:

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();

这将返回一个列表,其中每个客户端有一个元素和正确的日期。

您需要做的是按
client
分组,然后从末尾开始查找每个的最后一个
YES
。类似于此(
ClientList
是一个
列表
,您可能需要根据数据的位置对其进行更改):

编辑

曼苏尔·阿诺博耶夫(Mansur Anorboev)正确地建议按降序日期进行订购,从而消除了反向订购的需要,因此代码为:

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();

这将返回一个列表,每个客户端有一个元素,并且日期正确。

我可以提供一些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
虽然这不是所需的解决方案,但它会产生所需的结果。您可以创建一个存储过程并在代码中使用它

注:这是根据上述问题中提到的相同表格(和数据)进行测试的


我希望这将对您有所帮助。

我可以提供一些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
虽然这不是所需的解决方案,但它会产生所需的结果。您可以创建一个存储过程并在代码中使用它

注:这是根据上述问题中提到的相同表格(和数据)进行测试的


我希望这将对您有所帮助。

您可以通过两个查询轻松完成。抓取每个客户的所有“否”的列表。。。仅为每个客户端选择最后一个否。然后用它来查询最后一个“否”之后的第一个“是”的列表,只需两次查询即可轻松完成。抓取每个客户的所有“否”的列表。。。仅为每个客户端选择最后一个否。然后用它来按日期询问最后一个“否”之后的第一个“是”的列表。很好的解决方案。我认为最好使用降序(x=>x.date)并删除reverse(),因为@MansurAnorboev完全正确。答案编辑现在我看到了OP链接的第一个问题,这似乎不是很原创,因为@RenéVogt接受的答案就是这样。但是,
GroupBy
客户机部分可能是OP所需要的,所以我将留下这个答案。我认为最好使用降序(x=>x.date)并删除reverse(),因为@MansurAnorboev完全正确。答案编辑现在我看到了OP链接的第一个问题,这似乎不是很原创,因为@RenéVogt接受的答案就是这样。但是,
GroupBy
客户机部分可能是OP需要的,所以我留下这个答案