简体   繁体   中英

Join two tables where table A has a date value and needs to find the next date in B below the date in A

I got this table "A":

| id | date       |
===================
| 1  | 2010-01-13 |
| 2  | 2011-04-19 |
| 3  | 2011-05-07 |
| .. | ...        |

and this table "B":

| date       | value |
======================
| 2009-03-29 | 0.5   |
| 2010-01-30 | 0.55  |
| 2011-08-12 | 0.67  |

Now I am looking for a way to JOIN those two tables having the "value" column in "B" mapped to the dates in "A". The tricky part for me here is that table "B" only stores the change date and the new value. Now when I need this value in table "A" the SQL needs to look back what date is the next below the date it is asking the value for.

So in the end the JOIN of those tables should look like this:

| id | date       | value |
===========================
| 1  | 2010-01-13 | 0.5   |
| 2  | 2011-04-19 | 0.55  |
| 3  | 2011-05-07 | 0.55  |
| .. | ...        | ...   |

How can I do this?

-- Create and fill first table
CREATE TABLE `id_date` (
  `id` int(11) NOT NULL auto_increment,
  `iddate` date NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

INSERT INTO `id_date` VALUES(1, '2010-01-13');
INSERT INTO `id_date` VALUES(2, '2011-04-19');
INSERT INTO `id_date` VALUES(3, '2011-05-07');

-- Create and fill second table    
CREATE TABLE `date_val` (
  `mydate` date NOT NULL,
  `myval` varchar(4) collate utf8_bin NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

INSERT INTO `date_val` VALUES('2009-03-29', '0.5');
INSERT INTO `date_val` VALUES('2010-01-30', '0.55');
INSERT INTO `date_val` VALUES('2011-08-12', '0.67');

-- Get the result table as asked in question
SELECT iddate, t2.mydate, t2.myval
FROM `id_date` t1
JOIN date_val t2 ON t2.mydate <= t1.iddate
AND t2.mydate = ( 
SELECT MAX( t3.mydate ) 
FROM `date_val` t3
WHERE t3.mydate <= t1.iddate )

What we're doing:

  • for each date in the id_date table (your table A ),
  • we find the date in the date_val table (your table B )
  • which is the highest date in the date_val table (but still smaller than the id_date.date)

You could use a subquery with limit 1 to look up the latest value in table B:

select  id
,       date
,       (
        select  value
        from    B
        where   B.date < A.date
        order by
                B.date desc
        limit   1
        ) as value
from    A

I have been inspired by the other answers but ended with my own solution using common table expressions:

WITH datecombination (id, adate, bdate) AS 
(
SELECT id, A.date, MAX(B.Date) as Bdate
FROM tableA A
LEFT JOIN tableB B
ON B.date <= A.date
GROUP BY A.id, A.date
)
SELECT DC.id, DC.adate, B.value FROM datecombination DC
LEFT JOIN tableB B
ON DC.bdate = B.bdate 

The INNER JOIN return rows when there is at least one match in both tables. Try this.

Select A.id,A.date,b.value 
from A inner join B 
on A.date=b.date 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM