如何加入三个表并编写查询?

时间:2016-03-22 03:19:11

标签: sql join

表1:

Order_ID  Order_Type_ID    NAME      Date    
    1           1         Order1   03-07-16
    2           2         Order2   01-21-16

表2:

ID    Order_ID   Event_Date
1         1       03-21-16
2         2       03-21-16 

表3:

ID    Order_Type_ID   Repeat_Number   Repeat_Sequence
1         1                3                 2W
2         2                2                 2M

我需要通过连接上面三个表来编写查询。在表1中,我有订单列表及其类型和日期。表2主要存储订单发送时的事件。表3有一个订单类型的交叉引用,它表示需要发送订单的次数以及在什么时间间隔内。示例:具有type_Id 1的订单需要每两周从订单开始发送三次。同样,具有type_Id 2的订单需要每两个月开始两次订单发送。

因此,基于事件表(表2),我需要编写查询来计算订单仍需要发送的次数以及下次发送的日期。

例如,我需要编写的查询应该显示如下内容:

Order_ID     Sequence     NAME      Date    
    1           2        Order1   04-04-16
    1           3        Order1   04-18-16
    2           2        Order2   07-21-16

我可以使用子查询编写它,但想知道是否还有其他智能和快速的方法。

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

您需要使用递归CTE。假设它是SQL Server,查询将如下所示:

;with c as(
SELECT t1.Order_ID, t1.Order_Type_ID, t1.NAME, t1.Date, 
1 As Sequence, t3.Repeat_Number, t3.Repeat_Sequence
FROM #Table1 t1 INNER JOIN #Table3 t3 ON t1.Order_Type_ID = t3.Order_Type_ID
UNION ALL
SELECT c.Order_ID, c.Order_Type_ID, c.NAME, c.Date,
c.Sequence+1 As Sequence, c.Repeat_Number, c.Repeat_Sequence
FROM c WHERE c.Sequence < c.Repeat_Number)
select Order_ID, Order_Type_ID, Name, Sequence
, CASE WHEN Repeat_Sequence LIKE '%W' THEN DATEADD(week, Sequence * CAST(REPLACE(Repeat_Sequence, 'W', '') AS INT), Date)
       WHEN Repeat_Sequence LIKE '%M' THEN DATEADD(month, Sequence * CAST(REPLACE(Repeat_Sequence, 'M', '') AS INT), Date) END from c
order by Order_ID, Sequence

结果:

Order_ID    Order_Type_ID Name   Sequence    
----------- ------------- ------ ----------- -----------------------
1           1             Order1 1           2016-03-21 00:00:00.000
1           1             Order1 2           2016-04-04 00:00:00.000
1           1             Order1 3           2016-04-18 00:00:00.000
2           2             Order2 1           2016-03-21 00:00:00.000
2           2             Order2 2           2016-05-21 00:00:00.000

(5 row(s) affected)

如果您只想查看未来的订单,请过滤掉今天日期之前的任何记录。

请注意,此查询适用于Oracle或postgres,并对DATEADD函数进行了少量修改(在Postgres中,您将使用INTERVAL,在Oracle中,您可以在一周内添加7天,或者使用ADD_MONTHS数月)

<强>更新

如果您需要根据活动日期计算订单日期,可以将其加入查询,如下所示:

;with c as(
SELECT t1.Order_ID, t1.Order_Type_ID, t1.NAME, t2.Event_Date, 
1 As Sequence, t3.Repeat_Number, t3.Repeat_Sequence
FROM #Table1 t1 INNER JOIN #Table3 t3 ON t1.Order_Type_ID = t3.Order_Type_ID
INNER JOIN #Table2 t2 ON t1.Order_ID = t2.Order_ID
UNION ALL
SELECT c.Order_ID, c.Order_Type_ID, c.NAME, c.Event_Date,
c.Sequence+1 As Sequence, c.Repeat_Number, c.Repeat_Sequence
FROM c WHERE c.Sequence < c.Repeat_Number)
select Order_ID, Order_Type_ID, Name, Sequence
, CASE WHEN Repeat_Sequence LIKE '%W' THEN DATEADD(week, Sequence * CAST(REPLACE(Repeat_Sequence, 'W', '') AS INT), Event_Date)
       WHEN Repeat_Sequence LIKE '%M' THEN DATEADD(month, Sequence * CAST(REPLACE(Repeat_Sequence, 'M', '') AS INT), Event_Date) END from c
order by Order_ID, Sequence