2

So basically I was wondering how I can join two tables on the dates if they are different. The first table is my main tables which includes all my customers that have bought items. The date of purchase is a single point in the past:

Customers
    +--------+----------+-------+------------+
    | custid | Quantity | Price | ReportDate |
    +--------+----------+-------+------------+
    | 371965 |       12 |     2 | 9/1/2016   |
    | 371965 |        2 |     5 | 2/25/2018  |
    | 377958 |       45 |     3 | 9/1/2016   |
    | 270723 |       12 |  1.25 | 5/1/2014   |
    | 270723 |    10.86 |  1.25 | 6/1/2014   |
    | 270723 |    12.29 |   1.3 | 7/1/2014   |
    | 270723 |    12.29 |   1.4 | 9/15/2016  |
    +--------+----------+-------+------------+

So I would like to join my customers tables on the table with the discounts. The time when the discount was in effect is basically an entire period until a new discount was issued:

Discounts
    +----+-----------+----------+
    | id | startdate | discount |
    +----+-----------+----------+
    |  1 | 7/18/2013 |      0.1 |
    |  2 | 1/10/2014 |     0.25 |
    |  3 | 7/11/2016 |     0.11 |
    |  4 | 9/14/2016 |     0.12 |
    |  5 | 1/12/2017 |     0.15 |
    |  6 | 2/6/2017  |     0.22 |
    |  7 | 6/28/2017 |     0.09 |
    +----+-----------+----------+

So my goal is to link both tables and see which purchase date falls in the appropriate interval of the discounts. This would be my goal:

+--------+----------+-------+------------+----+-----------+----------+
| custid | Quantity | Price | ReportDate | id | startdate | discount |
+--------+----------+-------+------------+----+-----------+----------+
| 371965 |       12 |     2 | 9/1/2016   |  3 | 7/11/2016 |     0.11 |
| 371965 |        2 |     5 | 2/25/2018  |  7 | 6/28/2017 |     0.09 |
| 377958 |       45 |     3 | 9/1/2016   |  3 | 7/11/2016 |     0.11 |
| 270723 |       12 |  1.25 | 5/1/2014   |  2 | 41649     |     0.25 |
| 270723 |    10.86 |  1.25 | 6/1/2014   |  2 | 1/10/2014 |     0.25 |
| 270723 |    12.29 |   1.3 | 7/1/2014   |  2 | 1/10/2014 |     0.25 |
| 270723 |    12.29 |   1.4 | 9/15/2016  |  4 | 9/14/2016 |     0.12 |
+--------+----------+-------+------------+----+-----------+----------+
Dale K
  • 25,246
  • 15
  • 42
  • 71

3 Answers3

3

you can use OUTER APPLY to select the TOP 1 Discount that existed before the report date, ordered by date descending to get the most recent in operation

  SELECT C1.*,DQ.*  FROM CUSTOMERS C1 OUTER APPLY 
                 (SELECT TOP 1 D.* FROM Discounts D WHERE C1.ReportDate >= D.startDate  
                                       ORDER BY D.StartDate DESC) DQ
Cato
  • 3,652
  • 9
  • 12
2

You can join like this:

select c.*, d.*
from customers c inner join discounts d
on d.startdate = (select max(startdate) from discounts where startdate <= c.reportdate)

See the demo

forpas
  • 160,666
  • 10
  • 38
  • 76
2

Just another option

;with cte as (
Select A.* 
      ,B.*
      ,RN = row_number() over (Partition by custid,reportdate order by startdate desc)
 From Customers A
 Join Discounts B on B.startdate<=A.ReportDate
) 
Select * 
 From  cte 
 Where RN=1

dbFiddle

John Cappelletti
  • 79,615
  • 7
  • 44
  • 66