比较数据集C#中不同表的行

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了比较数据集C#中不同表的行相关的知识,希望对你有一定的参考价值。

我是SQL和C#的新手,我一直在寻找我遇到的问题的答案,但找不到完全解决它的问题。

我有一个链接到SQL Server数据库的C#应用​​程序。在我的数据库中,我有2个表,一个包含客户信息,另一个包含其帐户信息。如果特定客户没有帐户,则第二个表每个客户可以有超过1行,甚至没有行。

这是两个表:

客户表:

Customer table

账户信息表:

Account Information table

预期产出将是:

Franklin, Ben ($32) 
Jones, Thomas ($5) 
Tesla, Tesla  

我正在尝试编写一种方法,将所有客户加载到列表以及他们的帐户信息,但我收到每个客户的错误帐户信息(即Chequing和Saving)。当客户没有帐户或我正在比较的行具有不同的客户编号时,就会发生这种情况。所有名字都在我的名单上,但帐号信息错误。有更简单的方法吗?或者我做错了什么?我真的很感激任何帮助。

这是代码:

public List<CustomerAccountManager> LoadAllCustomers()
{
    SqlCommand cmd1, cmd2;
    SqlDataAdapter sqlda;

    DataSet sqlds = new DataSet();

    decimal? Chequing = null;
    decimal? Saving = null;
    int CustomerNumber = 0;

    string FirstName = string.Empty;
    string LastName = string.Empty;

    List<CustomerAccountManager> AllCustomers = new List<CustomerAccountManager>();

    cmd1 = new SqlCommand("SELECT Customer.CustomerNumber, FirstName, LastName FROM Customer", Connection);
    cmd2 = new SqlCommand("SELECT Account.CustomerNumber, AccountType, Balance FROM Account WHERE AccountType = 'C' OR AccountType = 'S' ", Connection);
    sqlds.Tables.Add("Customers");
    sqlds.Tables.Add("Acct");

    sqlda = new SqlDataAdapter(cmd1);
    sqlda.Fill(sqlds.Tables["Customers"]);

    sqlda = new SqlDataAdapter(cmd2);
    sqlda.Fill(sqlds.Tables["Acct"]);

    foreach (DataRow cust in sqlds.Tables[0].Rows)
    {
        foreach (DataRow acct in sqlds.Tables[1].Rows)
        {
            CustomerNumber = Convert.ToInt32(cust["CustomerNumber"]);
            int CustomerNumberAcct = Convert.ToInt32(acct["CustomerNumber"]);

            if (CustomerNumber == CustomerNumberAcct)
            {
                CustomerNumber = Convert.ToInt32(cust["CustomerNumber"]);
                FirstName = Convert.ToString(cust["FirstName"]);
                LastName = Convert.ToString(cust["LastName"]);
                string AcctType = Convert.ToString(acct["AccountType"]);

                if (AcctType == "C")
                    Chequing = Convert.ToDecimal(acct["Balance"]);

                if (AcctType == "S")
                    Saving = Convert.ToDecimal(acct["Balance"]);
            }
            else
            {
                for (int index = 0; index < sqlds.Tables[0].Rows.Count; index++)
                {
                    DataRow search = sqlds.Tables[0].Rows[index];
                    int customernosearch = Convert.ToInt32(search["CustomerNumber"]);

                    if (customernosearch == CustomerNumberAcct)
                    {
                        CustomerNumber = Convert.ToInt32(acct["CustomerNumber"]);
                        FirstName = Convert.ToString(cust["FirstName"]);
                        LastName = Convert.ToString(cust["LastName"]);
                        string AcctType = Convert.ToString(acct["AccountType"]);

                        if (AcctType == "C")
                            Chequing = Convert.ToDecimal(acct["Balance"]);
                        else
                            Chequing = null;

                        if (AcctType == "S")
                            Saving = Convert.ToDecimal(acct["Balance"]);
                        else
                            Saving = null;
                    }
                }
            }
        }

        AllCustomers.Add(new CustomerAccountManager(CustomerNumber, FirstName, LastName, Chequing, Saving));
    }

    return (AllCustomers);
}
答案

如果我理解你的正确性比你的查询看起来像这样

declare @customer table (number int, firstname varchar(50), lastname varchar(50))
declare @account table (number int, acctype varchar(50), balance decimal(16,2))

insert into @customer (number, firstname, lastname)
values (100000, 'Ben', 'Franklin'), (100001, 'Thomas', 'Jones'), (100002, 'Tesla', 'Tesla')

insert into @account (number, acctype, balance)
values (100000, 'C', 26), (100000, 'S', 6), (100001, 'C', 5)

SELECT c.Number, c.FirstName, c.LastName,
       ac.Balance AS CheckBalans,
       ac2.Balance AS SavingBalans,
       isnull(ac.Balance, 0) + isnull(ac2.Balance, 0) as total 
FROM @customer c
  LEFT JOIN @account ac ON ac.Number = c.Number
                       AND ac.AccType = 'C'
  LEFT JOIN @account ac2 ON ac2.Number = c.Number
                         AND ac2.AccType = 'S'

结果就是这样

Number  FirstName   LastName    CheckBalans SavingBalans    total   
------  ---------   --------    ----------- ------------    -----   
100000  Ben         Franklin    26          6               32  
100001  Thomas      Jones       5           null            5   
100002  Tesla       Tesla       null        null            0   

请记住,当有更多帐户类型时,此查询将不再有效

另一答案

这不是最好的做事方式,但我会坚持你的代码。只需删除else部分,就会弄乱一切。第一个if (CustomerNumber == CustomerNumberAcct)部分正在完成这项工作。

提示:您无需在DataSet中手动创建表格,Fill()函数将自动创建它们。

public List<CustomerAccountManager> LoadAllCustomers() {
    SqlCommand cmd1, cmd2;
    SqlDataAdapter sqlda;
    DataSet sqlds = new DataSet();

    decimal? Chequing = null;
    decimal? Saving = null;
    int CustomerNumber = 0;
    string FirstName = string.Empty;
    string LastName = string.Empty;

    List<CustomerAccountManager> AllCustomers = new List<CustomerAccountManager>();

    cmd1 = new SqlCommand("SELECT Customer.CustomerNumber, FirstName, LastName FROM Customer", Connection);
    cmd2 = new SqlCommand("SELECT Account.CustomerNumber, AccountType, Balance FROM Account WHERE AccountType = 'C' OR AccountType = 'S' ", Connection);
    //sqlds.Tables.Add("Customers");
    //sqlds.Tables.Add("Acct");
    sqlda = new SqlDataAdapter(cmd1);
    sqlda.Fill(sqlds.Tables["Customers"]);
    sqlda = new SqlDataAdapter(cmd2);
    sqlda.Fill(sqlds.Tables["Acct"]);

    foreach (DataRow cust in sqlds.Tables[0].Rows) {
        foreach (DataRow acct in sqlds.Tables[1].Rows) {
            CustomerNumber = Convert.ToInt32(cust["CustomerNumber"]);
            int CustomerNumberAcct = Convert.ToInt32(acct["CustomerNumber"]);
            if (CustomerNumber == CustomerNumberAcct) {
                CustomerNumber = Convert.ToInt32(cust["CustomerNumber"]);
                FirstName = Convert.ToString(cust["FirstName"]);
                LastName = Convert.ToString(cust["LastName"]);
                string AcctType = Convert.ToString(acct["AccountType"]);
                if (AcctType == "C")
                    Chequing = Convert.ToDecimal(acct["Balance"]);
                if (AcctType == "S")
                    Saving = Convert.ToDecimal(acct["Balance"]);
            }
        }
        AllCustomers.Add(new CustomerAccountManager(CustomerNumber, FirstName, LastName, Chequing, Saving));
     }
    return (AllCustomers);
}

或者,您可以使用LINQ在一行中实现所有这些功能。

编辑如果你想以同样的方式继续这样做,我建议将你的SQL查询合并到一个让你的生活更轻松的问题。像这样:

public List<CustomerAccountManager> LoadAllCustomers() {
    string sql;
    SqlCommand cmd;
    SqlDataAdapter sqlda;
    DataSet sqlds = new DataSet();

    decimal? Chequing = null;
    decimal? Saving = null;
    int CustomerNumber = 0;
    string FirstName = string.Empty;
    string LastName = string.Empty;

    List<CustomerAccountManager> AllCustomers = new List<CustomerAccountManager>();
    sql = @"SELECT c.CustomerNumber, c.FirstName, c.LastName,
                   ca.Balance AS Chequing, sa.Balance AS Saving
            FROM Customer c
            LEFT JOIN Account ca ON ca.CustomerNumber = c.CustomerNumber
                                 AND ca.AccountType = 'C'
            LEFT JOIN Account sa ON sa.CustomerNumber = c.CustomerNumber
                                 AND sa.AccountType = 'S'";
    cmd = new SqlCommand(sql, Connection);
    sqlda = new SqlDataAdapter(cmd);
    sqlda.Fill(sqlds);

    foreach (DataRow cust in sqlds.Tables[0].Rows) {
       CustomerNumber = Convert.ToInt32(cust["CustomerNumber"]);
       FirstName = Convert.ToString(cust["FirstName"]);
       LastName = Convert.ToString(cust["LastName"]);
       Chequing = Convert.ToDecimal(cust["Chequing"]);
       Saving = Convert.ToDecimal(cust["Saving"]);
       AllCustomers.Add(new CustomerAccountManager
                            (CustomerNumber, FirstName, LastName, Chequing, Saving));
     }
    return (AllCustomers);
}

以上是关于比较数据集C#中不同表的行的主要内容,如果未能解决你的问题,请参考以下文章

是否有使用Pandas限制数据透视表的行数的功能?

将数据集与 plotly 进行比较 - 用实线混合虚线

比较不同表的聚合函数

如何在不使用数据集的情况下在 Matlab 上比较不同的面部图像?

基于复合键比较表的记录

当数据集的列具有不同的行数时合并它们