根据相关记录的属性过滤掉记录

时间:2013-08-14 18:07:03

标签: c# linq entity-framework

我有这样的LINQ查询:

from a in _context.tblTradeSpends
orderby a.DealPeriod, a.CustomerNumber, a.LOB, a.VersionDate descending
select new
{
  DealPeriod = a.DealPeriod,
  CustomerNumber = a.CustomerNumber,
  LOB = a.LOB,
  PromoID = a.PromoID,
  VersionDate = a.VersionDate
}

以下是我的结果集中的一小部分示例(抱歉格式化):

DealPeriod  CustomerNumber   LOB    PromoID     VersionDate

2013        10001            PL     P0083312    12/04/2013 9:05
2013        10001            PL     P0083313    12/04/2013 9:05
2013        10001            PL     P0083314    12/04/2013 9:05
2013        10001            PL     P0085100    12/04/2013 9:05
2013        10001            PL     P0086169    12/04/2013 9:05
2013        10001            PL     P0083312    18/01/2013 10:51
2013        10001            PL     P0083313    18/01/2013 10:51
2013        10001            PL     P0083314    18/01/2013 10:51
2013        10001            PL     P0085100    18/01/2013 10:51
2013        10001            PL     P0083312    07/07/2013 15:41
2013        10001            PL     P0083313    07/07/2013 15:41
2013        10001            PL     P0083314    07/07/2013 15:41
2013        10001            SCF    P0083308    03/05/2013 11:27
2013        10001            SCF    P0083309    03/05/2013 11:27
2013        10001            SCF    P0085088    03/05/2013 11:27
2013        10001            SCF    P0085380    03/05/2013 11:27
2013        10001            SCF    P0085381    03/05/2013 11:27
2013        10213            SCF    P0086880    11/07/2013 20:23
2013        10213            SCF    P0086881    11/07/2013 20:23
2013        10213            SCF    P0086882    11/07/2013 20:23
2013        10213            SCF    P0086883    11/07/2013 20:23
2013        10213            SCF    P0083630    28/05/2013 13:38
2013        10213            SCF    P0083631    28/05/2013 13:38
2013        10213            SCF    P0083632    28/05/2013 13:38
2013        10213            SCF    P0083633    28/05/2013 13:38

我需要分析这些数据,所以我希望删除某些相关记录以便减少这些数据。我的规则是,我想删除所有具有相同交易期,客户编号和LOB字段的记录,其中没有一个版本日期超过2013年6月1日(2013年6月1日)

因此,在我的结果集中,我希望保留所有以2013|10001|PL开头的记录,因为某些记录的版本日期为07/17/2013

我会删除以2013|10001|SCF开头的记录,因为没有包含这些字段值的记录的版本日期超过2013年6月1日

我想保留以2013|10213|SCF开头的记录,因为其中一些记录的版本日期为11/07/2013。

修改

我试过King King的代码,我得到了一些不应该在那里的相关记录。以下是我将被过滤掉的两组:

2013    10039   SCF P0083145    05/02/2013 10:22
2013    10039   SCF P0083146    05/02/2013 10:22
2013    10039   SCF P0083147    05/02/2013 10:22
2013    10039   SCF P0085152    05/02/2013 10:22
2013    10039   SCF P0083145    1/22/2013 5:55:00 PM
2013    10039   SCF P0083146    1/22/2013 5:55:00 PM
2013    10039   SCF P0083147    1/22/2013 5:55:00 PM
2013    10039   SCF P0085152    1/22/2013 5:55:00 PM
2013    10039   SCF P0083145    12/05/2012 19:21
2013    10039   SCF P0083146    12/05/2012 19:21
2013    10039   SCF P0083147    12/05/2012 19:21
2013    10040   PL  P0084345    1/14/2013 10:27:00 AM
2013    10040   PL  P0084346    1/14/2013 10:27:00 AM
2013    10040   PL  P0084347    1/14/2013 10:27:00 AM
2013    10040   PL  P0084348    1/14/2013 10:27:00 AM
2013    10040   PL  P0084345    12/20/2012 10:15:00 PM
2013    10040   PL  P0084346    12/20/2012 10:15:00 PM
2013    10040   PL  P0084347    12/20/2012 10:15:00 PM
2013    10040   PL  P0084348    12/20/2012 10:15:00 PM

3 个答案:

答案 0 :(得分:1)

var fixedDate = DateTime.Parse("6/1/2013");
var result = _context.tblTradeSpends.GroupBy(x=>new {x.DealPeriod, x.CustomerNumber, x.LOB})     
                                    .Where(g=>g.All(x=>x.VersionDate <= fixedDate) || g.Count()==1)
                                    .SelectMany(g=>g);

我相信这段代码应该有效,所以我尝试创建OP示例中给出的示例列表并测试代码,结果如下:

2013 : 1001 : PL : P0083312 : 4/12/2013 12:00:00 AM
2013 : 1001 : PL : P0083313 : 4/12/2013 12:00:00 AM
2013 : 1001 : PL : P0083314 : 4/12/2013 12:00:00 AM
2013 : 1001 : PL : P0085100 : 4/12/2013 12:00:00 AM
2013 : 1001 : PL : P0086169 : 4/12/2013 12:00:00 AM
2013 : 1001 : PL : P0083312 : 1/18/2013 12:00:00 AM
2013 : 1001 : PL : P0083313 : 1/18/2013 12:00:00 AM
2013 : 1001 : PL : P0083314 : 1/18/2013 12:00:00 AM
2013 : 1001 : PL : P0085100 : 1/18/2013 12:00:00 AM
2013 : 1001 : PL : P0083312 : 12/7/2012 12:00:00 AM
2013 : 1001 : PL : P0083313 : 12/7/2012 12:00:00 AM
2013 : 1001 : PL : P0083314 : 12/7/2012 12:00:00 AM
2013 : 1001 : SCF : P0083308 : 5/3/2013 12:00:00 AM
2013 : 1001 : SCF : P0083309 : 5/3/2013 12:00:00 AM
2013 : 1001 : SCF : P0085088 : 5/3/2013 12:00:00 AM
2013 : 1001 : SCF : P0085380 : 5/3/2013 12:00:00 AM
2013 : 1001 : SCF : P0085381 : 5/3/2013 12:00:00 AM

据我了解OP的要求,此列表应该是OP想要的(删除所有不需要的条目后)。

答案 1 :(得分:0)

只需添加具有这些条件的where子句;

from a in _context.tblTradeSpends
where a.DealPeriod != 2013 && a.CutomerNumber != 10001 && a.LOB != SCF
orderby a.DealPeriod, a.CustomerNumber, a.LOB, a.VersionDate descending
select new
{
    DealPeriod = a.DealPeriod,
    CustomerNumber = a.CustomerNumber,
    LOB = a.LOB,
    PromoID = a.PromoID,
    VersionDate = a.VersionDate
}

where子句将过滤掉以2013|10001|SCF开头的所有记录。

答案 2 :(得分:0)

首先,您应该为匿名类型创建一个通用比较器:

public class MyEqualityComparer<T> : IEqualityComparer<T>
{
    Func<T, T, bool> _equalsFunction;
    Func<T, int> _hashCodeFunction;

    public MyEqualityComparer(
        Func<T, T, bool> equalsFunction, Func<T, int> hashCodeFunction)
    {
        if (equalsFunction == null) throw new ArgumentNullException();
        if (hashCodeFunction == null) throw new ArgumentNullException();

        _equalsFunction = equalsFunction;
        _hashCodeFunction = hashCodeFunction;
    }

    public bool Equals(T x, T y)
    {
        return _equalsFunction(x, y);
    }

    public int GetHashCode(T obj)
    {
        return _hashCodeFunction(obj);
    }
}

然后,使用以下查询:

var comp = new MyEqualityComparer<tblTradeSpend>(
            (x, y) => x.DealPeriod == y.DealPeriod && 
                x.CustomerNumber == y.CustomerNumber && 
                x.LOB == y.LOB, 
            obj => obj.DealPeriod.GetHashCode() ^ 
                 obj.CustomerNumber.GetHashCode() ^ 
                 obj.LOB.GetHashCode()
        );    

var q = (from a in _context.tblTradeSpends.AsEnumerable()
    where a.VersionDate < DateTime.Parse("6/1/2013")        
    select new
    {
        DealPeriod = a.DealPeriod,
        CustomerNumber = a.CustomerNumber,
        LOB = a.LOB,
        PromoID = a.PromoID,
        VersionDate = a.VersionDate
    }).Distinct(comp).OrderBy(o => o.DealPeriod)
                                 .ThenByDescending(o => o.CustomerNumber)
                                 .ThenByDescending(o => o.LOB)
                                 .ThenByDescending(o => o.PromoID).ToList();