外部結合の結果が想定と異なるが理由がピンとこない
SQLServerのお勉強で躓いています。
やろうとした事は no, timestamp の2列から成る'table_a'に、 no, datetime, value の3列から成る'table_b'を左外部結合するという事です(両テーブルとも no, datetime がプライマリキー)。
結合条件は下記の通りです。
- no: '='比較
- timestamp:'table_b'の timestamp の中で、'table_a'の timestamp 以下の最大の timestamp
あまり上手い説明ではないので、具体例として下記コードをご覧下さい。
IF object_id('table_a') IS NOT NULL
  DROP TABLE table_a;
CREATE TABLE table_a (
  no         INTEGER not null
 ,timestamp  DATE    not null
 ,CONSTRAINT pk_table_a PRIMARY KEY CLUSTERED (no, timestamp)
);
IF object_id('table_b') IS NOT NULL
  DROP TABLE table_b;
CREATE TABLE table_b (
  no         INTEGER not null
 ,timestamp  DATE    not null
 ,value      INTEGER not null
 ,CONSTRAINT pk_table_b PRIMARY KEY CLUSTERED (no, timestamp)
);
BEGIN TRANSACTION;
INSERT INTO table_a (no, timestamp) 
VALUES      (1, '2018-01-01')
           ,(1, '2018-01-04')
           ,(1, '2018-01-05')
           ,(2, '2018-01-01')
           ,(2, '2018-01-03')
           ,(2, '2018-01-09')
           ,(3, '2018-01-10')
           ,(3, '2018-01-11')
           ,(3, '2018-01-12')
;
INSERT INTO table_b (no, timestamp, value) 
VALUES      (1, '2018-01-01', 101)
           ,(1, '2018-01-02', 102)
           ,(2, '2018-01-02', 202)
           ,(3, '2017-01-01', 301)
           ,(3, '2018-01-12', 312)
;
COMMIT;
SELECT *
  FROM table_a
;
SELECT *
  FROM table_b
;
-- Query A: I can get what I want.
SELECT A.no
      ,A.timestamp
      ,B.value
  FROM (
    SELECT A.no
          ,A.timestamp
          ,(SELECT MAX(B.timestamp) 
              FROM table_b as B 
             WHERE B.no = A.no
               AND B.timestamp <= A.timestamp) as a_b_timestamp
      FROM table_a AS A
      ) as A
        LEFT OUTER JOIN table_b AS B
              ON  A.no = B.no
              AND A.a_b_timestamp = B.timestamp
 WHERE A.no in (1, 2)
;
 -- Query B: This query's result set is the same with A.
 SELECT A.no
      ,A.timestamp
      ,B.value
  FROM table_a AS A
         LEFT OUTER JOIN table_b AS B 
           ON A.no = B.no
          AND B.timestamp = (SELECT MAX(B.timestamp)    
                               FROM table_b as B 
                              WHERE B.no = A.no
                                AND B.timestamp <= A.timestamp)
 WHERE A.no in (1, 2)
;
-- Query C: The result set is far from what I expected, but I do not know reason.
SELECT A.no
      ,A.timestamp
      ,B.value
  FROM table_a AS A
         LEFT OUTER JOIN table_b AS B 
           ON A.no = B.no
          AND A.timestamp = (SELECT MAX(B.timestamp)    
                               FROM table_b as B 
                              WHERE B.no = A.no
                                AND B.timestamp <= A.timestamp)
 WHERE A.no in (1, 2)
 ;
テーブルに以下のデータが準備されます。
table_a:
no          timestamp
1           2018-01-01
1           2018-01-04
1           2018-01-05
2           2018-01-01
2           2018-01-03
2           2018-01-09
3           2018-01-10
3           2018-01-11
3           2018-01-12
table_b:
no          timestamp  value
1           2018-01-01 101
1           2018-01-02 102
2           2018-01-02 202
3           2017-01-01 301
3           2018-01-12 312
コード内にQuery A, B, C とコメントされたクエリがありますが、得られる結果セットは以下の通りです。私がほしかったのは A, B なのですが、 C だけが異なる結果セットを返しています。
Query A,B の結果セット(これが欲しかった!):
no          timestamp  value
1           2018-01-01 101
1           2018-01-04 102
1           2018-01-05 102
2           2018-01-01 NULL
2           2018-01-03 202
2           2018-01-09 202
Query C の結果セット(ほしいもの違う):
no          timestamp  value
1           2018-01-01 101
1           2018-01-01 102
1           2018-01-04 NULL
1           2018-01-05 NULL
2           2018-01-01 NULL
2           2018-01-03 NULL
2           2018-01-09 NULL
困っているのは C の結果がなぜ上のようになるのかが上手く説明出来ない点です。
どなたか、理由をクリアに説明して頂けないでしょうか。