如何解决如何获得每组的最小值和日期?
我有两个相关的MySQL表。我的目的是获取每个组的最小值以及与找到的每个最小值相关的日期。
==
表1和表3相关。
equals
表2记录了新值。
TABLE 1
> ------------+--------------+--------------+-----------+-----------------+
> -- Code -- | - IdGroup1 - | - IdGroup2 - | - State - | - NameProtocol -|
> ------------+--------------+--------------+-----------+-----------------+
> ZZ-100 | 11111111 | 1110000 | 1 | OSM1 |
> ------------+--------------+--------------+-----------+-----------------+
> ZZ-200 | 55555555 | 5550000 | 1 | OSM1 |
> ------------+--------------+--------------+-----------+-----------------+
> ZZ-300 | 99999999 | 9990000 | 1 | OSM1 |
我做了很多测试,但我仍然设法获得正确答案,通过以下查询获得了最佳近似值:
TABLE 3
> ---------------------+-------------------+----------------+
> -- NameProtocol -- | -- Description -- | -- Protocol -- |
> ---------------------+-------------------+----------------+
> ATC0 | d1 | UDP |
> ---------------------+-------------------+----------------+
> OSM1 | d2 | TCP |
> ---------------------+-------------------+----------------+
我的查询结果:
TABLE 2
> ---------+-----------------------+----------------+----------------+
> - Value -| ------- Date -------- | -- IdGroup1 -- | -- IdGroup2 -- |
> ---------+-----------------------+----------------+----------------+
> 10 | 2020-08-16 02:30:10 | 99999999 | 9990000 |
> ---------+-----------------------+----------------+----------------+
> 15 | 2020-08-16 02:31:10 | 99999999 | 9990000 |
> ---------+-----------------------+----------------+----------------+
> 20 | 2020-08-16 02:32:10 | 99999999 | 9990000 |
> ---------+-----------------------+----------------+----------------+
> 115 | 2020-08-16 02:31:20 | 55555555 | 5550000 |
> ---------+-----------------------+----------------+----------------+
> 120 | 2020-08-16 02:32:20 | 55555555 | 5550000 |
> ---------+-----------------------+----------------+----------------+
> 90 | 2020-08-16 02:35:20 | 11111111 | 1110000 |
> ---------+-----------------------+----------------+----------------+
> 100 | 2020-08-16 02:30:20 | 11111111 | 1110000 |
我只需要为找到的每个最小值添加日期。如何将其集成到查询中?
代码:
var query = Table2 //Outer Table
.Join(Table1,//Inner Table to join
p => new { p.IdGroup1,p.IdGroup2 },//Condition from outer table
e => new { e.IdGroup1,e.IdGroup2 },//Condition from inner table
(p,e) => new { //Result
Code = e.Code,Value = p.Value,Date = p.Date })
.GroupBy(gb => new { gb.Code })
.OrderBy(ob => ob.Key.Code)
.Select(s => new { Code = s.Key.Code,Value = (double?)s.Min(a => a.Value),Date = "?" }) // TODO: The date remains to be implemented.
.ToList();
解决方法
您可以尝试以下操作:
.Select(s =>
{
var values = s.OrderBy(x=>x.Value);
var firstValue = values.First();
return new
{
Code = s.Key.Code;
Value = (double?)firstValue.Value;
Date = firstValue.Date;
}
})
基本上,我们基于Value
属性对每个组中的项目进行排序。具有最小值的那个将是Ordering之后的第一个元素。然后我们选择该元素并读取其Value和Date,我们就完成了。
更新
一种快速的解决方案是在ToList
之后调用Join
。这样会将所有数据带到应用程序的内存中,然后您将在其中执行所有必需的处理。
.Join(Table1,p => new { p.IdGroup1,p.IdGroup2 },e => new { e.IdGroup1,e.IdGroup2 },(p,e) => new
{
Code = e.Code,Value = p.Value,Date = p.Date
})
.ToList()
.GroupBy(gb => new { gb.Code })
.OrderBy(ob => ob.Key.Code)
.Select(s =>
{
var values = s.OrderBy(x=>x.Value);
var firstValue = values.First();
return new
{
Code = s.Key.Code;
Value = (double?)firstValue.Value;
Date = firstValue.Date;
}
}).ToList();
,
对该请求最有效的查询是使用窗口函数,EF不支持该函数,而且我认为这永远不会发生。 因此,只要使用SQL并通过Dapper运行它即可。
SELECT
s.Code,s.Value,s.Date
FROM
(
SELECT
t1.Code,t2.Value,t2.Date,ROW_NUMBER() OVER (PARTITION BY t1.Code ORDER BY t2.Value) AS RN
FROM TABLE1 t1
JOIN TBALE3 t3 ON t3.NameOfProtocol = t1.NameOfProtocol
LEFT JOIN TABLE2 t2 ON t1.IdGroup1 = t2.IdGroup1 AND t1.IdGroup2 = t2.IdGroup2 AND t2.FechaCaudalHistorico <= @dateFilter
WHERE t3.Protocol = 'TCP'
) s
WHERE s.RN = 1
如果您不是纯粹的EF Core专家,但仍然需要LINQ,则可以尝试使用linq2db.EntityFrameworkCore扩展名,它具有这种可能性,并且可以通过LINQ编写查询:
var dateFilter = DateTime.Parse ("2020-09-16 03:00:00");
var rnQuery =
from t1 in Table1
join t3 in Table3 on t1.NameOfProtocol equals t3.NameOfProtocol
from t2 in Table2.Where(t2 => t1.IdGroup1 == t2.IdGroup1 && t1.IdGroup2 == t2.IdGroup2 && t2.FechaCaudalHistorico <= dateFilter)
.DefaultIfEmpty()
where t3.Protocol == "TCP"
select new
{
t1.Code,Value = Sql.ToNullable(t2.Value),Date = Sql.ToNullable(t2.Date),RN = Sql.Ext.RowNumber().Over().PartitionBy(t1.Code).OrderBy(t2.Value).ToValue()
};
var query = from s in rnQuery
where s.RN == 1
select new
{
s.Code,s.Date,};
// switch to alternative LINQ parser
query = query.ToLinqToDB();
var result = query.ToList();
结果,您将具有如上所述的相同SQL。
,您可以这样做:
library(tidyverse)
df <- tibble( "id" = c(1,1,2,3,3),"status"= as.factor(c("employed","employed","unemployed","other")))
df %>%
group_by(id) %>%
add_count(status,name = "count_types")
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。