双重分组以有效查找重复项

时间:2018-09-01 11:30:30

标签: c# linq-to-sql

假设我想找出所有使用一种以上货币的客户的交易。

例如,根据数据

CustomerID CurrencyID   Amount
1000       1            100.00
1000       1            200.00
1001       2            100.00
1001       2            200.00
1002       1            100.00
1002       2            200.00
1002       2            100.00
1003       1            100.00
1003       2            200.00

我想得到类似的结果

1002
    1002       1            100.00
    1002       2            200.00
    1002       2            100.00
1003
    1003       1            100.00
    1003       2            200.00

我可以使用类似的方法来获得结果

(from r in CustomerTransactions
    group r by new { r.CustomerID, r.CurrencyID } into results
    group results by results.Key.CustomerID into results2
    where results2.Count() > 1
    select results2.ToArray().SelectMany(a=>a);

但这并不高效,因为它会执行多个数据库查询。

有更好的方法吗?

2 个答案:

答案 0 :(得分:0)

并不是以其效率而著称。

我认为,如果您可以将结果传递到IEnumerable<T>,那就更快了!

IEnumerable<CustomerTransaction> results = db.ExecuteQuery<CustomerTransaction>
    (@" SELECT      CustomerID
                ,   CurrencyID
                ,   Amount
        FROM        CustomerTransactions    CT
        INNER JOIN  (
                        SELECT      CustomerID, COUNT(1) AS CurrencyCount
                        FROM        CustomerTransactions
                        GROUP BY    CustomerID
                        HAVING      COUNT(1) > 1
                    )                       CT2 ON CT2.CustomerID = CT.CustomerID
    );

我假设您有一个名为CustomerTransaction的课程。如果不是这样,则应该使用正确的class或在类型未知的情况下使用dynamic

答案 1 :(得分:0)

我喜欢使用两个嵌套字典:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("CustomerID", typeof(int));
            dt.Columns.Add("CurrencyID", typeof(int));
            dt.Columns.Add("Amount", typeof(decimal));

            dt.Rows.Add(new object[] {1000, 1, 100.00});
            dt.Rows.Add(new object[] {1000,1,200.00});
            dt.Rows.Add(new object[] {1001,2,100.00});
            dt.Rows.Add(new object[] {1001,2,200.00});
            dt.Rows.Add(new object[] {1002,1,100.00});
            dt.Rows.Add(new object[] {1002,2,200.00});
            dt.Rows.Add(new object[] {1002,2,100.00});
            dt.Rows.Add(new object[] {1003,1,100.00});
            dt.Rows.Add(new object[] {1003,2,200.00});

           Dictionary<int,Dictionary<int, decimal>> dict = dt.AsEnumerable()
                .GroupBy(x => x.Field<int>("CustomerID"), y => y)
                    .ToDictionary(x => x.Key, y => y
                       .GroupBy(a => a.Field<int>("CurrencyID"), b => b.Field<decimal>("Amount"))
                       .ToDictionary(a => a.Key, b => b.Sum(c => c)));

        }
    }
}