我正在解决这个问题:根据 table1 结果的条件,从连接 2 个或 3 个表的单行创建多个结果?虽然我希望我能接受Strawberry's
建议,但我不能,所以我现在尝试在 C# 中而不是通过 DB 做更多事情,但也试图聪明地了解我使用了多少 CPU。
对于规模,table1 可能有 50,000 条记录,codetype
其中包含必须评估的 20 个字段,然后才能匹配到 table2,它有大约 2,000 行,或者 table3,它可能有 200,000 行。为了避免敲击数据库,我将在内存中存储可能的内容,尽可能按日期限制结果,但我想避免每 20 个代码类型匹配有 2,000 个 foreach 循环。
首先,我从 table2 获得所需的结果,并将它们加载到 C# DataTable 中,存储为名为的变量descriptionLookup
:
id, description
13 Item 13 Description
15 Item 15 Description
17 Item 17 Description
18 Item 18 Description
21 Item 21 Description
28 Item 28 Description
45 Item 45 Description
表 3 为lookupTable
:
id, table2id
1 15
33 17
21 28
做一个简单的(不显示所有周围的代码,只是相关的):
var rawData = new DataTable();
using (OdbcCommand com = new OdbcCommand("SELECT id, description from table2", conn))
{
using (OdbcDataReader reader = com.ExecuteReader())
{
rawData.Load(reader);
conn.Close();
return rawData;
}
}
然后我将其分配给调用该函数的变量。现在我必须处理table1:
codeid1,codeid2,codeid3,...codeid20 ... codetype1,codetype2,codetype3,.....codetype20
18 13 1 33 0 0 1 1
13 21 45 0 0 1 0 0
使用 foreach 行,我需要评估每个 codetype 列是否为 1 或 0。当 codetype=1 时,我需要获取关联的 codeid,然后从我保存在内存中的数据中查找descriptionLookup
table2id是匹配id
inlookuptable
然后使用它来查找 table2 中关联字段的描述。
如果 codetype 为 0,我只需要匹配codeid
table2 中的相关描述字段。
我正在研究如何布局,我能想到的只有:
DataTable descriptionLookup= DB.ExecuteQuery("SELECT id, description from table2");
DataTable lookupTable= DB.ExecuteQuery("SELECT id, table2id from table3");
DataTable mainData= DB.ExecuteQuery("SELECT * from from table1");
foreach (var row in mainData)
{
var manDataId = row.GetColumn("id");
var subroutine = new Dictionary<string, string>();
for (var index = 1; index < 20; index++)
{
string description;
if (row.GetColumn("codetype" + index) == "1")
{
int idLookup = row.GetColumn(["codeid" +index]);
foreach (var row2 in lookupTable)
{
if (row3.GetColumn("id") == idLookup)
{
descriptionId = row3.GetColumn("table2id");
foreach (var row2 in descriptionLookup)
{
if (row.GetColumn("id") == descriptionId)
{
description = row2.GetColumn("description").ToString();
}
}
}
}
}elseif (row.GetColumn("codetype" + index) == "0")
{
descriptionId = row.GetColumn(["codeid" +index]);
foreach (var row2 in descriptionLookup)
{
if (row.GetColumn("id") == descriptionId)
{
description = row2.GetColumn("description").ToString();
}
}
}
subroutine.Add(manDataId.ToString(), description.ToString());
}
ArrayData.Add(subroutine);
}
我没有尝试运行上面的代码,所以那里可能有一两个问题,但它得到了使用foreach (var row3 in idLookup)
. 另一种方法似乎是进行数据库查询,但这似乎比仅仅遍历内存中的内容更密集,但似乎有一种更好的方法让我错过了如何获取id
或table2id
不使用 foreach。
为了使它成为历史上最长的问题:) 这是我到目前为止的 SQL:
SELECT table1.id, table1.field1, table1.field2,
table2.description, fee.amt as fee FROM table2
INNER JOIN table1
ON table2.id = table1.codeid1
OR table2.id = table1.codeid2
OR table2.id = table1.codeid3
OR table2.id = table1.codeid4
OR table2.id = table1.codeid5
OR table2.id = table1.codeid6
OR table2.id = table1.codeid7
OR table2.id = table1.codeid8
OR table2.id = table1.codeid9
OR table2.id = table1.codeid10
OR table2.id = table1.codeid11
OR table2.id = table1.codeid12
OR table2.id = table1.codeid13
OR table2.id = table1.codeid14
OR table2.id = table1.codeid15
OR table2.id = table1.codeid16
OR table2.id = table1.codeid17
OR table2.id = table1.codeid18
OR table2.id = table1.codeid19
OR table2.id = table1.codeid20
INNER JOIN fee ON table2.id = fee.id
WHERE table1.codetype1 = 0
AND table1.codetype2 = 0
AND table1.codetype3 = 0
AND table1.codetype4 = 0
AND table1.codetype5 = 0
AND table1.codetype6 = 0
AND table1.codetype7 = 0
AND table1.codetype8 = 0
AND table1.codetype9 = 0
AND table1.codetype10 = 0
AND table1.codetype11 = 0
AND table1.codetype12 = 0
AND table1.codetype13 = 0
AND table1.codetype14 = 0
AND table1.codetype15 = 0
AND table1.codetype16 = 0
AND table1.codetype17 = 0
AND table1.codetype18 = 0
AND table1.codetype19 = 0
AND table1.codetype20 = 0
只要没有任何codetype
具有 1 的记录,这将非常有效,否则将跳过该记录。可能不会有任何一行都codeid / codetype
被填满,也不会出现codetype
全盘为 1 以匹配此查询的逆查询的情况。