【问题标题】:filtering records based on two other tables根据另外两个表过滤记录
【发布时间】:2013-10-02 18:50:54
【问题描述】:

我需要在 MS Access 数据库中生成一个活跃客户列表。所有过去和现在的客户都存储在客户表中。但是,确定活动状态的标准需要从另外两个表中得出:进入和退出。如果客户的进入日期之后没有退出日期,则客户被认为是活跃的。但是,令人困惑的是,具有退出日期的前客户可以通过获得新的进入日期再次成为客户。

以下是存储此信息的三个表结构的相关部分:

customers table  
    customerID  
    name  

intake table  
    intakeID  
    customerID  
    intakeDate  

exit date  
    exitID  
    customerID  
    exitDate  

一个客户可以有多个入库记录和多个退出记录。所以 SQL 语句的伪代码需要看起来像这样:

SELECT customerID, name FROM customers  
WHERE ((most recent intakeDate)>(most recent exitDate(if any)))

这在真正的 SQL 中应该是什么样子?对于 MS Access 2010 数据库。显然,连接是必要的。但是什么类型的连接呢?它需要看起来如何?

【问题讨论】:

    标签: sql ms-access join subquery ms-access-2010


    【解决方案1】:
    SELECT ActiveCustomers.*, tblAddress.* FROM 
    (
      SELECT customers.name, customers.customerID,
      (
        SELECT COUNT(intakeDate) 
        FROM intake 
        WHERE customers.customerID = intake.customerID AND Len(intakeDate & '') > 0
      ) AS IntakeCount,
      (
        SELECT COUNT(exitDate) 
        FROM exit 
        WHERE customers.customerID = exit.customerID AND Len(exitDate & '') > 0
      ) AS ExitCount
      FROM customers 
    ) AS ActiveCustomers
    INNER JOIN tblAddress ON ActiveCustomers.customerID = tblAddress.customerID
    WHERE IntakeCount > ExitCount
    AND tblAddress.CurrentAddress = True
    

    【讨论】:

    • 谢谢。 +1 快速周到的回复。您建议计算进出日期,而不是明确返回比任​​何退出日期更近的进出日期?此外,我将在 MS Access 中创建一个报告,该报告从其他三个表中提取数据,以填写此查询识别的活动客户的信息。您对我将如何设置它有任何一般性的 cmets 吗?我是要嵌套更多的 SQL 语句,还是让报表中的每个字段进行自己的查询,以根据该查询为其行标识的 customerID 查找其他信息?
    • 可以,但不必对其他表进行子查询。如果使用上述方法,您可以加入ActiveCustomers。例如FROM ActiveCustomers INNER JOIN OtherTable ON ActiveCustomers.CustomerID = OtherTable.CustomerID。然后在我有SELECT * 的地方,你可以指定所有你想要的字段。
    • 再次感谢您。令人困惑的是我应该如何捆绑 ActiveCustomers 代码。假设我还想添加一个字段,其中包含每个活动客户当前地址的电话号码,如果在地址表中该客户的地址记录之一中指定了当前地址,或者如果没有地址被检查为当前地址,则将电话号码留空.我在哪里放置以下内容:“INNER JOIN tblAddress ON ActiveCustomers.customerID = tblAddress.customerID WHERE tblAddress.CurrentAddress=-1”?希望看到你的回答后,能自己把其他的片段拼起来
    • 在我的代码中,“SELECT customers.name, customers.customerID”行实际上是“SELECT customers.customerID, customers.firstName, customers.lastName”。但是无论我如何排序这三个字段,Access 只能看到前两个,并给出一个对话框,询问列表中第三个字段的值。目前,它在生成的数据表中将 lastName 留空。知道如何让 Access 查看所有三个字段吗?
    • 我没有看到上面的 SQL 是如何工作的。第 3--4 行肯定会有错误吗?
    【解决方案2】:
    select * from 
        (SELECT  CustomerID, Name, MAX(intakeDate) AS intakeDate, MAX(exitDate) AS exitDate
        FROM  customerstable 
        INNER JOIN intaketable 
        ON customerID = customerID 
        INNER JOIN  exitdate 
        ON intaketable.customerID = exitdate.customerID
        GROUP BY dbo.customerstable.CustomerID ) c
    where intakeDate > exitDate
    

    【讨论】:

    • 谢谢。当我尝试在访问中运行它时,它给了我一个对话框,说缺少一个运算符,并且消息开始的代码点是 ON customerID=customerID INNER JOIN... 有什么建议吗?
    • 抱歉,那行应该是:ON customerstable.customerID = carrytable.customerID
    • 谢谢。我实际上已经尝试过了。我的代码现在和你的一样一字不差,但是访问仍然说缺少某种运算符。是否缺少逗号或其他内容?
    • 抱歉 - 按行分组是错误的。删除“dbo”。在customerstable.CustomerID 之前。应该如下所示:GROUP BY customerstable.CustomerID。我习惯为 SQL Server 编写 SQL,并包含在 MS Access 中无效的架构。
    【解决方案3】:

    我喜欢@sqlgrl 的方法,即只查看每个客户最近的进出,但我已经对其进行了调整,以使用特定于 MS Access 的语法,而且我认为,它稍微加强了连接逻辑:

    select c.*
    from ([customers table] as c
    inner join (
      select customerID, max(exitDate) as lastOut
      from [exit date]
      group by customerID
    ) as [out]
    on c.customerID = [out].customerID)
    inner join (
      select customerID, max(intakeDate) as lastIn
      from [intake table]
      group by customerID
    ) as [in]
    on c.customerID = [in].customerID
    where [in].lastIn > [out].lastOut
    

    上面基本上是说:

    • 建立每个客户最近退出日期的列表
    • 建立每个客户最近摄入日期的列表
    • 将两个列表与客户表连接起来
    • 如果客户最近的进入日期晚于他们最近的退出日期,则将此客户包括在最终输出中

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-26
      • 2015-09-03
      • 2021-05-31
      • 1970-01-01
      • 1970-01-01
      • 2021-10-15
      • 1970-01-01
      • 2011-10-12
      相关资源
      最近更新 更多