如何根据可能更改的日期范围在表中选择值

时间:2019-03-24 13:14:28

标签: sql sql-server

我似乎找不到一个专门解决我在这里想要做的事情的问题,但是如果不是这种情况,我深表歉意。

我有一个示例表:

    type|start_date|end_date  |cost|

    bananas|2019-01-01|2019-01-31|100
    bananas|2019-02-01|2019-02-28|95
    juice  |null      |null      |55

以此类推。该表的要点是,“食物”或其他任何东西都可以根据不同的时间范围以不同的价格出售,但是有些商品例如果汁,当日期更改时(即保持不变)不会受到影响。

在另一个表中,我想根据上表中的日期范围查找一个值。

例如:

customerId|transaction_date|item   |quantity|

abc123    |2019-01-25      |bananas|4
abc126    |2019-02-06      |bananas|4
abc128    |2019-02-09      |juice  |1

因此,前两个客户购买了香蕉,但一月份购买了一个,二月份购买了一个。 然后另一个顾客买了果汁。 如何根据其他表格返回正确的相应费用。

我尝试在日期为BETWEEN的情况下进行操作,但这会疏远定价表中不存在的任何其他日期。 我也尝试过使用CASE来解决这个问题,但无济于事。

什么是最好的方法?

我希望结果将产生具有以下内容的联接表:

customerId|transaction_date|item   |quantity|cost|

abc123    |2019-01-25      |bananas|4       |100
abc126    |2019-02-06      |bananas|4       |95
abc128    |2019-02-09      |juice  |1       |55

上述条件将cost列放在何处?

3 个答案:

答案 0 :(得分:2)

您可以在左侧联接上使用ISNULL。

SELECT P.*, C.cost
FROM Purchases P 
LEFT JOIN Product_Costs C ON P.item = C.type 
      AND P.transaction_date >= ISNULL(C.start_date, P.transaction_date) 
      AND P.transaction_date <= ISNULL(C.end_date, P.transaction_date);

修改了Nick的小提琴:http://sqlfiddle.com/#!18/e366b/6

答案 1 :(得分:1)

您可以使用相关子查询:

select t2.*,
       (select t1.cost
        from table1 t1
        where t1.type = t2.type and
              t2.transaction_date >= t1.start_date and
              t2.transaction_date <= t1.end_date 
       ) as cost
from table2 t2;

或者,您可以使用left join

select t2.*, t1.cost
from table2 t2 left join
     table1 t1
     on t1.type = t2.type and
        t2.transaction_date >= t1.start_date and
        t2.transaction_date <= t1.end_date ;

编辑:

您可以使用NULL处理OR值:

select t2.*, t1.cost
from table2 t2 left join
     table1 t1
     on t1.type = t2.type and
        (t2.transaction_date >= t1.start_date or
         t1.start_date is null
        ) and
        (t2.transaction_date <= t1.end_date or
         t1.end_date is null
        );

答案 2 :(得分:1)

您可以使用外部申请:

  SELECT p.*,
  c.cost
  FROM Purchases AS p
      OUTER APPLY (
          SELECT TOP 1 c.cost
              FROM Product_Costs AS c
              WHERE p.transaction_date BETWEEN c.start_date AND c.end_date
                  AND c.type = p.Item
      ) AS c;

我已经使用您的示例数据创建了一个Sql Fiddle:http://sqlfiddle.com/#!18/e366b/2/0