SQL Server:重复连接4个表

时间:2013-10-18 10:25:51

标签: sql sql-server join duplicates

我有四张桌子

  • Customers - PK:CustomerID
  • Events - PK:EventID
  • Customers_Events - 加入包含两个FK CustomerIDEventID
  • 的表格
  • Customer_Checkins - 包含时间戳列(CheckinDateTime)和对CustomerID的FK引用

我想要这样的输出

CustomerName   EventName    CheckinDateTime
------------   ----------   ---------------
Peter          Christmas    2012-12-25 00:27:48.350
Peter          Valentines   2013-02-14 01:19:36.113
Peter          Spring       2013-05-20 02:13:53.710

问题是我得到了这个结果

CustomerName   EventName    CheckinDateTime
------------   ----------   ---------------
Peter          Christmas    2012-12-25 00:27:48.350
Peter          Christmas    2013-02-14 01:19:36.113
Peter          Christmas    2013-05-20 02:13:53.710
Peter          Valentines   2012-12-25 00:27:48.350
Peter          Valentines   2013-02-14 01:19:36.113
Peter          Valentines   2013-05-20 02:13:53.710
Peter          Spring       2012-12-25 00:27:48.350
Peter          Spring       2013-02-14 01:19:36.113
Peter          Spring       2013-05-20 02:13:53.710

每个有效记录三次返回

这是我用来获取上面结果的脚本

SELECT DISTINCT 
    Customers.Firstname, Events.EventName, CustomerCheckins.CheckinDateTime
FROM         
    CustomerCheckins 
INNER JOIN
    Customers_Events ON CustomerCheckins.CustomerID = Customers_Events.CustomerID 
LEFT OUTER JOIN
    Customers ON Customers_Events.CustomerID = Customers.CustomerID 
RIGHT OUTER JOIN
    Events ON Customers_Events.EventID = Events.EventID
WHERE     
    (Customers_Events.CustomerID = 1887)

我真的很感激帮助解决这个问题。我觉得我已经尝试过脚本中的每个组合。

2 个答案:

答案 0 :(得分:2)

您应该使用grouping代替distinct

SELECT Customers.Firstname, Events.EventName, MIN(CustomerCheckins.CheckinDateTime)
FROM         
    CustomerCheckins 
        INNER JOIN Customers_Events ON CustomerCheckins.CustomerID = Customers_Events.CustomerID 
        INNER JOIN Customers ON Customers_Events.CustomerID = Customers.CustomerID 
        INNER JOIN Events ON Customers_Events.EventID = Events.EventID
WHERE Customers_Events.CustomerID = 1887
GROUP BY Customers.Firstname, Events.EventName

答案 1 :(得分:1)

问题在于您的数据库设计。

您的数据模型不允许您将签到与特定事件相关联。

如果您的事件表包含startdate和enddate,则问题是可解决的; 然后你可以在你的加入中添加时间限制。

修改

幸运的是,事件表中有一个startdate和endate,因此以下SQL应该可以工作:

          SELECT Customers.Firstname, Events.EventName, MAX(CustomerCheckins.CheckinDateTime)
            FROM CustomerCheckins 
      INNER JOIN Customers_Events 
              ON CustomerCheckins.CustomerID = Customers_Events.CustomerID 
 LEFT OUTER JOIN Customers 
              ON Customers_Events.CustomerID = Customers.CustomerID 
RIGHT OUTER JOIN Events 
              ON Customers_Events.EventID = Events.EventID
             AND events.StartDateTime <= CustomerCheckins.CheckinDateTime
             AND Events.EndDateTime > CustomerCheckins.CheckinDateTime
           WHERE (Customers_Events.CustomerID = 1887)
        GROUP BY Customers.Firstname, Events.EventName

请注意,如果用户在活动期间签入的时间超过一次,则需要该组。

检查时选择MIN或MAX取决于您是否要在活动期间显示第一次或最后一次检查。

旁注:

我对SQL Server查询优化器不是很熟悉,但它可能很难为此查询创建一个好的执行计划。 如果您计划在实时系统中使用它,请确保在使用大量数据加载表后对其进行测试。