1

这与我之前提出的一个问题非常相关,并且得到了一个很好的答案 - 现在变得更加复杂了: 如何从 DataTable 对象中选择不同的列组合,并将另一列作为条件?

我正在使用 C# 2010。

我有一个我正在使用的 DataTable 对象,它具有以下结构(并填充了示例数据):

"name"    "ID"    "hiredate"    "termdate"
Bobby     1        5/1/2011       7/1/2011
Peggy     2        5/1/2011
Lucy      4                       7/3/2012
Jenny     3        5/2/2011
Jenny     3        5/2/2013
Jenny     3        5/2/2011       6/1/2011
Peggy     2        5/1/2011
Lucy      4        6/1/2012

我想过滤此 DataTable 以仅保留不同的(“ID”、“hiredate”)组合。这个问题有两个主要特点: 1 - 如果有重复的(“ID”,“hiredate”)条目,应该保留信息最多的条目(即现有的“termdate”)。2 - 一些条目没有“雇用日期”,只有“任期日期”。在准确处理条件 1 之前,它们需要与适当的“雇用日期”相匹配(至少我认为它们是这样)。

数据表是从 csv 和可能添加的用户输入创建的,而不是从数据库查询创建的,否则我的生活会轻松很多。

因此,执行此操作后的结果表将是:

"name"    "ID"    "hiredate"    "termdate"
Bobby     1        5/1/2011       7/1/2011
Peggy     2        5/1/2011
Jenny     3        5/2/2013
Jenny     3        5/2/2011       6/1/2011
Lucy      4        6/1/2012       7/3/2012

Jenny 有两个条目,因为她出现了两个不同的“雇用日期”值,其中一个也重复了 - 删除了没有“任期日期”的条目。Lucy 的两行已合并 - 它们有互补的缺失日期。

关于如何在 C# 中执行此操作的任何建议?同样,我正在使用 DataTable 对象。我仍然需要保留“name”和“termdate”字段——如果我没有,那么我可以获得一个不同的(“ID”、“hiredate”)列表,但它们确实需要保留。

在我最初的问题中,没有任何条目具有“termdate”但没有“hiredate”,这是公认的解决方案,对我来说效果很好:

            DataView dv = new DataView(dt);
            dv.Sort = "ID ASC, HireDate DESC, TermDate DESC";

            string lastID = "0";
            List<DateTime> addedHireDatesForUser = new List<DateTime>();

            foreach (DataRowView drv in dv)
            {
                if (drv["ID"].ToString() != lastID)
                {
                    addedHireDatesForUser = new List<DateTime>();
                    addedHireDatesForUser.Add(DateTime.Parse(drv["HireDate"].ToString()));

                    // NEXT ID, ADD ROW TO NEW DATATABLE
                }
                else if (!addedHireDatesForUser.Contains(DateTime.Parse(drv["HireDate"].ToString())))
                {
                    addedHireDatesForUser.Add(DateTime.Parse(drv["HireDate"].ToString());

                    // NEXT DATE, ADD ROW TO NEW DATATABLE
                }

                lastID = drv["ID"].ToString();
            }

我正在寻找的是一种(至少在某种程度上)优雅的方式来处理作为此过程的一部分缺少“雇用日期”的条目的帮助。我可以编写一个非常低效的循环来匹配所有这些,但由于该表中有(实际上)数千个条目,我不得不想知道是否有更好的方法。

我很感激任何建议!

4

1 回答 1

0

这是否附加了 SQL 查询?如果是这样,查询类似于

SELECT name, ID, hiredate, termdate from table

可以切换到

--First query returns combined record where they have a null in hiredate and one in termdate
SELECT t1.name, t1.ID, max(t2.hiredate) as hiredate, max(t1.termdate) as termdate from table t1
inner join table t2 on t1.id = t2.id and t1.hiredate is null and t2.hiredate is null
GROUP by t1.name, t1.ID
UNION
--Second query returns full records where both hiredate and termdate are there
SELECT name, ID, hiredate, termdate from table t1
where t1.hiredate is not null and termdate is not null
UNION
--Third query returns all records with a different hiredate that have no termdate and include them
SELECT name, ID, hiredate, termdate from table t1
LEFT OUTER JOIN t2 on t1.ID = t2.ID and t1.hiredate = t2.hiredate
where t1.termdate is null and t2.hiredate is null

这应该涵盖您讨论的所有情况。

于 2013-10-24T20:43:04.147 回答