【问题标题】:How to use SQL query to get earliest Date from multiple Tables?如何使用 SQL 查询从多个表中获取最早的日期?
【发布时间】:2016-04-13 22:21:30
【问题描述】:

如何使用 SQL 查询从多个表中获取最早的日期?

摘要(2016 年 1 月 10 日修订): 我需要来自 3 个表(A、B、C)的信息,TableC 没有主键,因此我将为每个 [B_ID] 获取多个 [C_Date] 记录。

' Description of Database:
'    A Ms Access database file: "c:\DB\Data.mdb"
'    It has 3 Tables: [TableA], [TableB], [TableC]
'    TableA with Fields [A_ID], [A_Design]
'    TableB with Fields [B_ID], [A_ID], [B_InventoryNum], [B_BlankNum] 
'    TableC with Fields [B_ID], [C_Name], [C_Value], [C_Date] 
'    TableA Primary Key is [A_ID]
'    TableB Primary Key is [B_ID]
'    TableC has no Primary Key, hence, for each [B_ID], there are multiple [C_Date]

以下是来自 TableC 的数据的一个示例 B_ID 名称 值 C_Date 73 直径 35.375 98 年 1 月 27 日 73 直径 35.376 98 年 1 月 27 日 73 直径 35.375 98 年 4 月 12 日 73 直径 35.374 98 年 7 月 19 日 73 直径 35.374 98 年 9 月 23 日 73 直径 35.374 99 年 3 月 30 日 73 直径 35.375 99 年 10 月 24 日 73 直径 35.374 99 年 10 月 24 日 73 身高 22.491 98 年 1 月 27 日 73 身高 21.908 98 年 4 月 12 日 73 身高 21.908 98 年 7 月 19 日 73 身高 21.915 98 年 9 月 23 日 73 身高 21.901 99 年 3 月 30 日 73 身高 21.909 99 年 10 月 24 日 73 身高 22.041 98 年 1 月 27 日

查询顺序如下:

1. 使用 where [A_Design] LIKE '%99%' 从 TableA 中获取 [A_ID] 2. 使用“左连接”链接到 TableB 3.再次使用'Left Join'链接到TableC

'Left Join'只是一个例子,可以用'Inner Join'代替。

我当前的 Sql 查询将返回 B_ID (73) 的所有 15 行,但我只需要一个日期 - 最早的日期 (27-Jan-98),我对其他字段也不感兴趣,例如[名称],[值]。

VB.NET 中的以下代码将检索多个 [C_Date]。 如果我只想要最早的 [C_Date],我应该如何修改我的 SQL 脚本?任何建议和反馈将不胜感激!

如果你对VB.NET不感兴趣,请直接跳到Sql字符串,问题是SQL语法,它独立于任何特定的编程语言。

非常感谢@PhilipXY 和@Rory 提出的仅在Access 环境中进行测试的建议、示例代码和信息指南,终于解决了我的问题。

下面的 SQL 是来自查询的 MS Access SQL 视图的工作副本。

SELECT Distinct [TableA].[A_Design], [TableA].A_ID, [TableB].B_ID, [TableB].B_InventoryNum, [TableB].[B_BlankNum], [TableC].C_Date, [TableC].B_ID FROM ([TableA] INNER JOIN [TableB] ON [TableA].A_ID = [TableB].B_ID) INNER JOIN [TableC] ON [TableB].B_ID = [TableC].B_ID GROUP BY [TableA].[A_Design], [TableA].A_ID, [TableB].B_ID, [TableB].B_InventoryNum, [TableB].[B_BlankNum], [TableC].C_Date, [TableC].B_ID HAVING ((([TableA].[A_Design]) Like '99') AND (([TableC].C_Date)=(SELECT TOP 1 Min([TableC].C_Date) FROM [TableC] Where [TableC].B_ID=[TableB].B_ID)));

使用这个修改后的 SQL,现在我可以从 TableC 中检索以下信息:

B_ID C_日期 73 98 年 1 月 27 日

问题解决了!我想为@PhilipXY 和@Rory 投5 票。 (我假设 5 是我可以投票的最高点。)

VB.NET 代码:
======================================== ========================== 导入 System.Data.OleDb 导入 System.Windows.Forms ' 1. 只需在你的winform上添加一个DataGridView1控件, ' 2.然后添加一个按钮(命名:'btnTest') ' 3. 下面是按钮单击处理程序,它将从数据库中检索信息并将其显示在“DataGridView1”控件上。
Private Sub btnTest_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnTest.Click

    Dim MDBConnString_ As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\DB\Data.mdb;"
    Dim cnn As OleDbConnection = New OleDbConnection(MDBConnString_)
    cnn.Open()

    Dim Sql As String
    Sql = "SELECT " & "([A_Design]+Format([B_InventoryNum],""0000"")) AS DesignCodePK, [TableA].[A_ID], [A_Design], [TableB].[B_ID], [B_InventoryNum], [B_BlankNum], [C_Date] FROM ([TableA] LEFT JOIN [TableB] On [TableA].[A_ID] = [TableB].[A_ID]) " & " LEFT JOIN [TableC] On [TableB].[B_ID] = [TableC].[B_ID] Where [A_Design] LIKE '%99%' Order by [A_Design], [B_InventoryNum], [C_Date] "

    Dim cmd As New OleDbCommand(Sql, cnn)
    Dim DataAdapter As New OleDbDataAdapter(cmd)
    Dim ds As System.Data.DataSet
    ds = New System.Data.DataSet

    DataAdapter = New OleDbDataAdapter(cmd)
    DataAdapter.Fill(ds, "joined")
    DataGridView1.DataSource = ds.Tables("joined")
    cnn.Close()
End Sub

【问题讨论】:

  • 如果问题是关于查询的,那么您应该简单地在问题中提出。您在寻找什么查询?
  • @philipxy TableC 共有 4 个字段([B_ID]、[C_Name]、[C_Value]、[C_Date])。通过 TableB 的左连接,我得到了 [B_ID]。通过使用[B_ID],我可以获得多个[C_Date],但我只需要最早的[C_Date],我尝试使用Min([C_Date]),没有任何运气。
  • @Shawn 我正在寻找只返回最早日期的查询([C_Date] 字段将返回多条记录)。详细信息请参考我的问题帖,谢谢您的回复。
  • @philipxy 更准确地说,我真的不知道如何在我的 Query 中使用 Min(),您能帮忙修改 Sql 字符串以添加到 Min() 中吗?谢谢。
  • 您似乎只想为每个 B_ID 返回一行?即,如果您要 GROUP BY B_ID 那么对于具有给定 B_ID 的每一组行,您会想要一行 HAVING MIN C_DATE?

标签: sql vb.net ms-access


【解决方案1】:

要获取 B_ID 的最小日期,请使用

select min(c_date) from TableC where b_id = XXXX

获取所有最小日期

select b_id, min(c_date) as MinDate
from TableC group by b_id

然后您可以将该查询连接到其他表:

select *
from TableB
left join (
    select b_id, min(c_date) as MinDate
    from TableC group by b_id
) as minimumDates
    on minimumDates.b_id = TableB.b_id

如果您遇到查询语法问题,请尝试直接针对 MS Access 运行 SQL,而不是通过 VB。这将更容易检查哪些工作/不工作。如果你不能让 GROUP BY 工作,那么从一个尽可能简单的新查询开始,就像我上面的第一个 select 一样。忘记你真正想要的列,只需让一个简单的查询工作,然后一次添加JOINs 和WHERE 和列。

【讨论】:

  • 感谢您的回答。我在Sql下试过了,没用。 Sql = "SELECT " & "([A_Design]+Format([B_InventoryNum],""0000"")) AS DesignCodePK, [TableA].[A_ID], [A_Design], [TableB].[B_ID], [B_InventoryNum ], [B_BlankNum], Min([C_Date]) FROM ([TableA] LEFT JOIN [TableB] On [TableA].[A_ID] = [TableB].[A_ID]) " & " LEFT JOIN [TableC] On [TableB ].[B_ID] = [TableC].[B_ID] where [A_Design] LIKE '%99%' Order by [A_Design], [B_InventoryNum], [C_Date] "
  • 这里是错误消息:{“您尝试执行的查询不包括指定的表达式 '[A_Design]+Format([B_InventoryNum],"0000")' 作为聚合的一部分函数。"}
  • 我对Access不是很熟悉,但是我建议你暂时忘记你的VB代码,直接通过MS Access运行SQL。这样,您可以更轻松地更改内容并查看结果。您还删除了妨碍可读性的字符串格式"&。格式更好的 SQL 确实有助于理解查询为何/不起作用。
  • 对于更新后的 SQL 查询,您需要 GROUP BY 才能使用聚合函数 MIN()。首先尽可能简化查询以使MIN()GROUP BY 正常工作,然后构建它。
  • @WayneJ。 - 这里不鼓励不相关的后续问题。如果您还有其他问题,那么ask a new question。您始终可以在其他问题中包含link to this question 以提供上下文。
猜你喜欢
  • 1970-01-01
  • 2022-01-06
  • 2022-11-28
  • 2022-08-17
  • 1970-01-01
  • 2021-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多