包含自身连接(使用子查询)并报告不存在的值(空值)的 MS Access 查询

MS Access query that includes a join to itself (using a subquery) and reports values that do not exist (null values)

我有以下 table 命名价格:

VERTEXID TIMEID PRICE
6001 20191231 104.3
6001 20181231 115.3
6001 20171231 138.3
6001 20161231 122.3
6002 20191231 102.3
6002 20190931 123.3
6002 20190631 167.3
6002 20181231 202.3
6002 20171231 402.3
6002 20170931 162.3

我想在 MS Access sql 中编写一个查询,它将找到 table 中的前 5 个 TIMEID,按降序排列,然后将为每个 VERTEXID I select 在 WHERE 子句中 return 对应的值 。如果记录不存在,我希望查询 return 存在的先前值(这是首选)或 null。这是我需要的输出示例:

VERTEXID TIMEID PRICE
6001 20191231 104.3
6001 20190931 104.3 (or null)
6001 20190631 104.3 (or null)
6001 20181231 115.3
6001 20171231 138.3
6002 20191231 102.3
6002 20190931 123.3
6002 20190631 167.3
6002 20181231 202.3
6002 20171231 402.3

我目前的情况是这样的:

SELECT P1.VERTEXID, P1.TIMEID, P1.PRICE
FROM PRICES P1
RIGHT JOIN (
                        SELECT DISTINCT TOP 5 P2.TIMEID
                        FROM   PRICES P2
                        WHERE   P2.TIMEID <= 20191231
                        ORDER BY P2.TIMEID DESC
                        ) P3
            ON P3.TIMEID = P1.TIMEID
WHERE P1.VERTEXID IN (6001,6002) AND P1.TIMEID <= 20191231
ORDER BY P1.VERTEXID, P1.TIMEID DESC

但它不会输出我需要的。非常感谢任何帮助!

如果您想要每个顶点 ID 的最近 5 行:

select p.*
from prices as p
where p.vertexid in (6001, 6002) and
      p.timeid in (select top 5 p2.timeid
                   from prices as p2
                   where p2.vertexid = p.vertexid
                   order by p2.timeid desc
                  );

您在查询中对时间进行了过滤,但您提出的实际问题中并未提及。鉴于过滤是开启的timeid,你需要的话直接放在子查询里就可以了。

编辑:

如果你想为所有顶点id使用相同的五个时间id(如果它们存在的话),你可以使用:

select p.*
from prices as p
where p.vertexid in (6001, 6002) and
      p.timeid in (select top 5 p2.timeid
                   from prices as p2
                   where p2.vertexid in (6001, 6002)
                   order by p2.timeid desc
                  );

如果你只想为两个顶点共享timeids,你可以使用:

      p.timeid in (select top 5 p2.timeid
                   from prices as p2
                   where p2.vertexid in (6001, 6002)
                   group by p2.timeid
                   having count(*) = 2
                   order by p2.timeid desc
                  );

好了:

SELECT J1.VERTEXID, J1.TIMEID, P4.PRICE
FROM (
    SELECT DISTINCT P1.VERTEXID, P3.TIMEID
    FROM PRICES P1,
            (SELECT DISTINCT TOP 5 P2.TIMEID
            FROM PRICES P2
            WHERE P2.TIMEID <= 20191231
            ORDER BY P2.TIMEID DESC
            ) P3
    ) J1
LEFT JOIN PRICES P4 ON J1.VERTEXID = P4.VERTEXID AND J1.TIMEID = P4.TIMEID
ORDER BY J1.VERTEXID, J1.TIMEID DESC

您必须根据需要添加过滤条件。

基本上您必须执行以下操作:

  • 执行 CROSS JOIN 以获得 VERTEXID 和 TIMEID 的所有组合(即 J1
  • 然后 LEFT JOIN 这个结果到 table 本身并得到相应的 PRICE 值

缺少价格将为 NULL。