【问题标题】:JOIN two tables by completed transaction通过已完成的事务连接两个表
【发布时间】:2017-02-05 02:22:57
【问题描述】:

我正在尝试使用 MS Access 数据库在 C# 中开发一个协议,该数据库可以由用户打印出来。我有不同的表(库存、贷款、退货),可以在这里看到:

思路是这样的:

有一个 inventory 表(参见图片上的 Inventory),其中有一个具有一定数量的产品。

还有带有日期戳的贷款流程(参见图片上的贷款)的表格: “吉姆在 2000 年 1 月 1 日 08:00 借出 3 把锤子” 等等

和一个带有日期戳的返回过程(参见返回图像): “吉姆要归还 3 把锤子……” 等等

所以我想合并这两个表以创建所有已完成交易的概览,其中完成的交易是借出和归还。

但是,当我执行我的代码时,这是 result(参见图片上的结果):

private void btn1_Click(object sender, EventArgs e)
{
    OleDbConnection con = new OleDbConnection(@"Provider = Microsoft.Jet.OLEDB.4.0; Data Source = D:\Access\keymgt_db_test.mdb");
    oda = new OleDbDataAdapter(@"SELECT * FROM Lending LEFT JOIN Returning ON Lending.EmployeeIndex=Returning.EmployeeIndex AND Lending.Datestamp<Returning.Datestamp", con);
    dta = new DataTable();
    oda.Fill(dta);
    dataGridView1.DataSource = dta;
}

在防止重复 ID 的 dataGridView 中,所需的结果应该看起来像 理想(见图)。

如何做到这一点?非常感谢您!

【问题讨论】:

  • 如果这是一个Access数据库,为什么mysql标签?

标签: c# sql ms-access


【解决方案1】:

正如另一个答案中提到的,我还将LendingReturning 表合并到一个Transaction 表中。

但是,我了解有时您确实希望对交易的每一方都有单独的记录。这使您能够进行更复杂的交易...... Alice 借给 Bob,Bob 借给 Charlie,Charlie 借给 David,后者最终将其还给 Alice。每笔交易都有自己的记录。

如果您不需要这些更复杂的事务,包含LentFromLentToLentDateReturnDate 列的单个记录就足够了,并且可能更容易实现和报告。但是,如果您确实想支持更复杂的事务,则每次更改都需要单独记录。不管怎样,把它放在一张桌子上。

【讨论】:

  • 谢谢 Joel,我认为这在编写解决方案以防止结果表左侧出现重复 ID 时会更容易。问题是:这个解决方案是什么样子的?
【解决方案2】:

除了@onedaywhen 和@Joel 的答案之外,您可以将“借出”和“归还”表合并到一个表中,但也可以单独跟踪每个项目。也就是说,而不是

ProductLent  LentTo  LentQty  DateLent
-----------  ------  -------  ----------
Hammer       Gord          3  2016-09-26

你可以有

ProductLent  LentTo  DateLent    DateReturned
-----------  ------  ----------  ------------
Hammer       Gord    2016-09-26
Hammer       Gord    2016-09-26
Hammer       Gord    2016-09-26

这样,如果我今天只退回一个 Hammer,那么只需将一件物品标记为退回只是一个问题

ProductLent  LentTo  DateLent    DateReturned
-----------  ------  ----------  ------------
Hammer       Gord    2016-09-26  2016-09-27
Hammer       Gord    2016-09-26
Hammer       Gord    2016-09-26

(我看到您在示例“返回”表中暗示了此类活动,其中 Jim 不会同时返回所有 5 个锤子。)

如果您需要将多项目贷款显示为单个“交易”,您始终可以运行一个查询,对 GROUPed BY(ProductLent、LentTo、DateLent)的各个行进行计数以获取 LentQty。

这种方法可能看起来很浪费,但现代数据库非常擅长“汇总”单个项目,并且“汇总”几乎总是比将单行“拆分”成多行容易得多。 (再举一个例子,考虑一下采购订单上的一个订单项,您订购了 5 个单位,却发现您的供应商运送了 3 个单位并将另外 2 个单位延期交货。)

【讨论】:

  • 谢谢戈德,我想我明白你的意思了。我考虑过汇总,但协议要求,每笔借贷/归还都带有日期戳。所以真正的问题是如何防止 Result 表左侧的重复 ID。我考虑建立条件来处理特定行,直到交易(借贷)完成。
【解决方案3】:

如果您在编写简单查询 (SQL DML) 时遇到问题,那么您应该怀疑您的设计 (SQL DDL)。

在我看来,您已将一个实体(一个借出期)拆分为两行。

我最成功的方法是将start_dateend_date 属性放在同一行。借用项目时,start_date 将设置为当前时间戳值,而尚未发生的 end_date 将设置为遥远的未来时间戳值,例如 #2099-12-31 23:59:59#表示无穷大(有点像在 .NET 中使用 DateTime.MaxValue,但 MS Access 的 DATETIME 无法处理其精度)。

这个无穷大的“幻数”在代码中表现得很好,例如

...where now() between start_date and end_date

以前我使用 null(对我来说是一个罕见的例外情况!)作为结束日期,但发现我经常不得不处理缺失值!例如

...where now() between start_date and IIf(end_date IS NULL, #2099-12-31 23:59:59#, end_date )

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-28
    • 1970-01-01
    • 2020-09-15
    • 2020-09-02
    相关资源
    最近更新 更多