for循环内的C#查询只返回一个值

时间:2017-09-28 08:03:33

标签: c# sql-server winforms for-loop

我正在构建一个C#WinForms应用程序,用户可以使用随机生成的机箱号列表检查特定操作的机箱号是否连接到部件列表,如果是,则计算可用的部件号。每个底盘编号都连接到一个零件清单(或不连接)。该特定零件清单包含通过类型定义注释链接到底盘编号的零件。例如,100024有一个定义D13K420音符的类型,因此它应该在部分列表13080554中看到该类型定义音符(计数3)。

我在MSSQL Server中有两个数据表。一个用于底盘编号:

| ID | chassis_number | model | build_date | factory | type_defining_note | partlist |
|----|----------------|-------|------------|---------|--------------------|----------|
|  1 |         100000 |     1 | 2014-01-04 |       2 |            D13K500 | 13080553 |
|  2 |         100001 |     1 | 2014-01-06 |       2 |            D13K460 | 13080554 |
|  3 |         100002 |     1 | 2014-01-12 |       2 |            D13K460 | 13080554 |
|  4 |         100023 |     1 | 2014-01-15 |       2 |            D13K540 | 13080553 |
|  5 |         100024 |     1 | 2014-01-20 |       1 |            D13K420 | 13080554 |
|  6 |         100025 |     1 | 2014-01-26 |       2 |            D13K500 | 13080553 |
|  7 |         122312 |     1 | 2014-02-08 |       1 |            D13K500 |        0 |
|  8 |         104560 |     1 | 2014-02-09 |       1 |            D13K460 |        0 |
|  9 |         100045 |     1 | 2014-03-04 |       2 |            D13K540 |        0 |
| 10 |         100046 |     1 | 2014-03-12 |       2 |            D13K540 |        0 |

部分清单:

| ID | part_list_no | part_list_description | model | position | part_number | part_description | quantity | type_defining_note | action | action_type |
|----|--------------|-----------------------|-------|----------|-------------|------------------|----------|--------------------|--------|-------------|
|  1 |     13080553 |   Oil filter (Engine) |     1 |        1 |    21803087 |           Filter |        1 |            D13K500 |      1 |           P |
|  2 |     13080553 |   Oil filter (Engine) |     1 |        1 |    21803088 |           Filter |        1 |            D13K540 |      1 |           P |
|  3 |     13080553 |   Oil filter (Engine) |     1 |        2 |    24523486 |       Oil cooler |        1 |            D13K500 |      1 |           S |
|  4 |     13080553 |   Oil filter (Engine) |     1 |        2 |    24523486 |       Oil cooler |        1 |            D13K540 |      1 |           S |
|  5 |     13080553 |   Oil filter (Engine) |     1 |        3 |    27647538 |           O-ring |        2 |            D13K500 |      1 |           S |
|  6 |     13080553 |   Oil filter (Engine) |     1 |        3 |    27647538 |           O-ring |        2 |            D13K540 |      1 |           S |
|  7 |     13080553 |   Oil filter (Engine) |     1 |        4 |    23984567 |             Pipe |        1 |                    |      0 |             |
|  8 |     13080553 |   Oil filter (Engine) |     1 |        5 |    23984558 |             Pipe |        1 |                    |      0 |             |
|  9 |     13080554 |   Oil filter (Engine) |     1 |        1 |    21803085 |           Filter |        1 |            D13K420 |      1 |           P |
| 10 |     13080554 |   Oil filter (Engine) |     1 |        1 |    21803086 |           Filter |        1 |            D13K460 |      1 |           P |
| 11 |     13080554 |   Oil filter (Engine) |     1 |        2 |    24523486 |       Oil cooler |        1 |            D13K420 |      1 |           S |
| 12 |     13080554 |   Oil filter (Engine) |     1 |        2 |    24523482 |       Oil cooler |        1 |            D13K460 |      1 |           S |
| 13 |     13080554 |   Oil filter (Engine) |     1 |        3 |    27647538 |           O-ring |        2 |            D13K420 |      1 |           S |
| 14 |     13080554 |   Oil filter (Engine) |     1 |        3 |    27647538 |           O-ring |        2 |            D13K460 |      1 |           S |
| 15 |     13080554 |   Oil filter (Engine) |     1 |        4 |    23984567 |             Pipe |        1 |                    |      0 |             |
| 16 |     13080554 |   Oil filter (Engine) |     1 |        5 |    23984558 |             Pipe |        1 |                    |      0 |             |

使用简单联接进行的连接:FULL OUTER JOIN part_list ON chassis.part_list = part_list.part_list_number

我想要达到的目的是:

| chassis_number | parts |
|----------------|-------|
|         100000 |     3 |
|         100001 |     3 |
|         100002 |     3 |
|         100023 |     3 |
|         100024 |     3 |
|         100025 |     3 |
|         100045 |     0 |
|         100046 |     0 |
|         104560 |     0 |
|         122312 |     0 |

如果底盘编号和零件清单之间存在连接,请通过类型定义注释计算具有有效连接的所有零件编号,如果不是简单地返回0。

我能够创建一个对部件进行计数的查询,但是将它放在C#中的for循环中只返回一个底盘编号的部件,或者如果给出多个底盘编号,则返回0:

SELECT COUNT(chassis.chassis_number) AS parts FROM chassis FULL OUTER JOIN part_list ON chassis.part_list = part_list.part_list_number WHERE chassis.chassis_number = @chassisnumber AND part_list.action = @action AND part_list.type_defining_note LIKE(SELECT chassis.type_defining_note FROM chassis WHERE chassis.chassis_number = @chassisnumber)

应该返回计算部分的代码:

public static void CheckPackages()
{
    for (int i = 0; i < chassisNumber.Count; i++)
    {
        Variables.searchChassisNumber = Convert.ToInt32(chassisNumber[i]);

        try
        {
            command.Connection = connection;
            command.CommandText = "SELECT COUNT(chassis.chassis_number) AS parts FROM chassis FULL OUTER JOIN part_list ON chassis.part_list = part_list.part_list_number WHERE chassis.chassis_number = @chassisnumber AND part_list.action = @action AND part_list.type_defining_note LIKE(SELECT chassis.type_defining_note FROM chassis WHERE chassis.chassis_number = @chassisnumber)";
            command.CommandType = CommandType.Text;

            SqlParameter paramChassisNumber = new SqlParameter
            {
                ParameterName = "@chassisnumber",
                SqlDbType = SqlDbType.Int,
                Direction = ParameterDirection.Input,
                Value = Variables.searchChassisNumber
            };

            SqlParameter paramAction = new SqlParameter
            {
                ParameterName = "@action",
                SqlDbType = SqlDbType.Int,
                Direction = ParameterDirection.Input,
                Value = Variables.selectedAction
            };

            for (int j = 0; j < part.Count; j++)
            {
                part.RemoveAt(j);
            }

            command.Parameters.Add(paramChassisNumber);
            command.Parameters.Add(paramAction);

            SqlDataReader reader = command.ExecuteReader();
            while (reader.Read())
            {
                part.Add((int)reader["parts"]);
            }
            reader.Close();
            command.Parameters.Clear();

            partList.Add(new Parts(chassisNumber[i], part[i]));
        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }
    }
}

我在这里读到其他答案,在循环中运行查询并不太明智(性能问题,在我的情况下,我的代码中可能还有其他一些失败)。

链接到SQLFiddle上的示例数据库: http://sqlfiddle.com/#!6/6d4638/74

问题是:我有哪些选择可以获得有效的解决方案?我应该在for循环中放入查询,还是创建一个新的参数化查询,还是应该重建整个数据库以使其工作?

1 个答案:

答案 0 :(得分:1)

是。避免在前端循环,这对性能不利。

你几乎走在正确的轨道上。

你需要机箱LEFT OUTER JOIN到零件清单上的3个条件partlist,type_defining_note和action

然后GROUP由chassis_number和couting partlist(而不是count(*),因为你只想计算partlist表中存在的那些)

select chassis.chassis_number, count(partlist.part_list_no) as parts
from   chassis
       left join partlist on  chassis.partlist = partlist.part_list_no
                          and chassis.type_defining_note = partlist.type_defining_note
                          and partlist.action = '1' 
group by chassis.chassis_number