Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.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# 加快linq group by语句的速度_C#_Linq - Fatal编程技术网

C# 加快linq group by语句的速度

C# 加快linq group by语句的速度,c#,linq,C#,Linq,我有一张这样的桌子 UserID Year EffectiveDate Type SpecialExpiryDate 1 2015 7/1/2014 A 1 2016 7/1/2015 B 10/1/2015 表中没有ExpriyDate,因为它只在一年内有效,所以可以从生效日期加上一年来计算到期日期 我想得到的结果是,今年的生效日期和明年的到期日期 UserID EffectiveDate

我有一张这样的桌子

UserID   Year   EffectiveDate   Type    SpecialExpiryDate
     1   2015   7/1/2014        A   
     1   2016   7/1/2015        B       10/1/2015
表中没有ExpriyDate,因为它只在一年内有效,所以可以从生效日期加上一年来计算到期日期

我想得到的结果是,今年的生效日期和明年的到期日期

UserID   EffectiveDate   ExpiryDate
     1    7/1/2014        7/1/2016
如果用户的类型是B,那么将有一个特殊的到期日,因此对于此人,结果将是

UserID   EffectiveDate   ExpiryDate
     1    7/1/2014        10/1/2015
这是我写的代码

var result = db.Table1
            .Where(x => x.Year>= 2015 && (x.Type == "A" || x.Type == "B"))
            .GroupBy(y => y.UserID)
            .OrderByDescending(x => x.FirstOrDefault().Year)
            .Select(t => new
                         {
                             ID = t.Key,
                             Type = t.FirstOrDefault().Type,
                             EffectiveDate = t.FirstOrDefault().EffectiveDate,
                             ExpiryDate = t.FirstOrDefault().SpecialExpiryDate != null ? t.FirstOrDefault().SpecialExpiryDate : (t.Count() >= 2 ? NextExpiryDate : CurrentExpiryDate)
                          }
                    );
代码可以得到我需要的结果,但问题是在结果集中大约有10000条记录,这大约需要5到6秒。该项目是一个网络搜索API,所以我想加快它,有没有更好的方法来做查询

编辑

对不起,我犯了一个错误,在select子句中应该是

EffectiveDate=t.LastOrDefault.EffectiveDate

但在C的Linq中,它不支持将LastOrDefault函数转换为sql,这导致了新的问题,获取组中第二项的最简单方法是什么?

试试以下方法:

var result =
    db
        .Table1
        .Where(x => x.Year>= 2015 && (x.Type == "A" || x.Type == "B"))
        .GroupBy(y => y.UserID)
        .SelectMany(y => y.Take(1), (y, z) => new
        {
            ID = y.Key,
            z.Type,
            z.EffectiveDate,
            ExpiryDate = z.SpecialExpiryDate != null
                ? z.SpecialExpiryDate 
                : (t.Count() >= 2 ? NextExpiryDate : CurrentExpiryDate),
            z.Year,
        })
        .OrderByDescending(x => x.Year);
.SelectManyy=>y.Take1有效地执行代码的.FirstOrDefault部分。通过一次而不是多次执行此操作,您可以极大地提高速度

在我使用类似结构的查询执行的测试中,当使用您的方法时,我运行了以下子查询:

SELECT t0.increment_id
FROM sales_flat_order AS t0
GROUP BY t0.increment_id

SELECT t0.hidden_tax_amount
FROM sales_flat_order AS t0
WHERE ((t0.increment_id IS NULL AND @n0 IS NULL) OR (t0.increment_id = @n0))
LIMIT 0, 1
-- n0 = [100000001]

SELECT t0.customer_email
FROM sales_flat_order AS t0
WHERE ((t0.increment_id IS NULL AND @n0 IS NULL) OR (t0.increment_id = @n0))
LIMIT 0, 1
-- n0 = [100000001]

SELECT t0.hidden_tax_amount
FROM sales_flat_order AS t0
WHERE ((t0.increment_id IS NULL AND @n0 IS NULL) OR (t0.increment_id = @n0))
LIMIT 0, 1
-- n0 = [100000002]

SELECT t0.customer_email
FROM sales_flat_order AS t0
WHERE ((t0.increment_id IS NULL AND @n0 IS NULL) OR (t0.increment_id = @n0))
LIMIT 0, 1
-- n0 = [100000002]
对于每个记录编号,这将继续进行两个子查询

如果我运行我的方法,我会得到一个查询:

SELECT t0.increment_id, t1.hidden_tax_amount, t1.customer_email
FROM (
  SELECT t2.increment_id
  FROM sales_flat_order AS t2
  GROUP BY t2.increment_id
  ) AS t0
CROSS APPLY (
  SELECT t3.customer_email, t3.hidden_tax_amount
  FROM sales_flat_order AS t3
  WHERE ((t3.increment_id IS NULL AND t0.increment_id IS NULL) OR (t3.increment_id = t0.increment_id))
  LIMIT 0, 1
  ) AS t1

我的方法应该快得多。

您可以使用数据库中的视图动态生成计算数据

类似这样的伪代码:

Create View vwUsers AS 
    Select 
        UserID, 
        Year, 
        EffectiveDate, 
        EffectiveData + 1 as ExpiryDate,   // <-- 
        Type, 
        SpecialExpiryDate
    From 
        tblUsers

只需将LINQ查询连接到该查询。

是否要显示/返回10K结果?您应该寻找分页。@Habib,它是一个API,所以我必须一次返回所有数据,我想您可以将多少逻辑推送到数据库?在处理大量数据方面,LINQ不如大多数服务器/大型机好。@pita我不熟悉任何主动促进通过分页返回10k同时记录的API。此外,如果您要返回10k行数据,当然可以设置一个期望值。那些FirstOrDefault让我高度怀疑此查询是否确实执行了您希望它首先执行的操作。感谢您的回答,但我刚刚发现我的错误,我需要从LastOrDefault项获取生效日期,所以我不能只使用take1来获取每个组的第一项谢谢,实际上我在sql数据库中创建了一个存储过程,代码类似于select。。。。。从Users join中选择MINEffectiveDate、MAXsome计算以获取ExpiryDate@pita-然后在分组前按降序进行排序。那么.Take1应该可以工作了。