Oracle SQL:选择最大减去1除了最低(获取以前的数据版本)

时间:2016-03-15 15:53:25

标签: sql oracle

我有一个表,其中多个报告权限存储其数据的多个版本(由整数版本号索引)。我为该表创建了一个仅选择最新版本的视图:

SELECT * FROM MYTABLE NATURAL JOIN 
(
  SELECT ENTITY, MAX(VERSION) VERSION FROM MYTABLE 
  GROUP BY ENTITY
)

现在我想创建另一个视图,该视图总是在最新之前选择一个版本以进行比较。我考虑过使用MAX() - 1(见下文),它通常有效,但问题是这排除了仅报告一个版本的实体的条目。

SELECT * FROM MYTABLE NATURAL JOIN 
(
  SELECT ENTITY, MAX(VERSION) - 1 VERSION FROM MYTABLE 
  GROUP BY ENTITY
)

编辑:为清楚起见,如果只有一个版本可用,我希望报告那个版本。例如,请考虑下表:

ENTITY  VERSION VALUE1
10000   1       10
10000   2       11
12000   1       50
14000   1       15
14000   2       16
14000   3       17

现在我想通过我的查询获得

ENTITY  VERSION VALUE1
10000   1       10
12000   1       50
14000   2       16

但是根据我当前的查询,12000的条目退出。

3 个答案:

答案 0 :(得分:1)

您可以将任务表述为:获取每个实体的两个最高可用版本,并从中获取每个实体的最小版本。您可以通过使用ROW_NUMBER对记录进行排名来确定n个最高版本。

select entity, min(version)
from
(
  select 
    entity, 
    version, 
    row_number() over (partition by entity order by version desc) as rn
  from mytable 
)
where rn <= 2
group by entity;

无论实体是否只有一条或两条或更多条记录,无论是否有任何可能的差距,都可以使用。

答案 1 :(得分:0)

如果MAX(VERSION)只有一个VERSION值,您可以加入ENTITY

SELECT * 
FROM MYTABLE 
NATURAL JOIN 
(
  SELECT ENTITY, 
         CASE 
            WHEN MAX(VERSION) <> MIN(VERSION) THEN MAX(VERSION) - 1 
            ELSE MAX(VERSION)
         END VERSION 
  FROM MYTABLE 
  GROUP BY ENTITY
)

答案 2 :(得分:0)

您可以使用分析查询来避免自联接:

SELECT ENTITY, VERSION, LAST_VERSION
FROM (
  SELECT ENTITY, VERSION,
    NVL(LAG(VERSION) OVER (PARTITION BY ENTITY ORDER BY VERSION), VERSION) AS LAST_VERSION,
    RANK() OVER (PARTITION BY ENTITY ORDER BY VERSION DESC) AS RN
  FROM MYTABLE
)
WHERE RN = 1;

它可以同时找到当前版本和之前的版本,因此如果需要,您可以使用单个视图来获取这两个版本。

LAG(VERSION) OVER (PARTITION BY ENTITY ORDER BY VERSION)获取每个实体的先前版本号,对于第一个记录版本,它将为null;所以NVL用于在这种情况下再次获取当前版本。 (您也可以使用更标准的COALESCE函数)。如果您有任何版本号,也可以使用版本号。

RANK() OVER (PARTITION BY ENTITY ORDER BY VERSION DESC)为每个实体/版本对分配一个序号,DESC表示最高版本排名为1,第二个最高版本为2,等等。我假设你赢了' t有一个实体的重复版本 - 如果你这样做,可以使用DENSE_RANK并决定如何打破关系,但似乎不太可能。

对于您的数据,您可以看到它产生的内容:

SELECT ENTITY, VERSION, VALUE1,
  LAG(VERSION) OVER (PARTITION BY ENTITY ORDER BY VERSION) AS LAG_VERSION,
  NVL(LAG(VERSION) OVER (PARTITION BY ENTITY ORDER BY VERSION), VERSION) AS LAST_VERSION,
  RANK() OVER (PARTITION BY ENTITY ORDER BY VERSION DESC) AS RN
FROM MYTABLE
ORDER BY ENTITY, VERSION;

    ENTITY    VERSION     VALUE1 LAG_VERSION LAST_VERSION         RN
---------- ---------- ---------- ----------- ------------ ----------
     10000          1         10                        1          2
     10000          2         11           1            1          1
     12000          1         50                        1          1
     14000          1         15                        1          3
     14000          2         16           1            1          2
     14000          3         17           2            2          1

所有这些都是在内联视图中完成的,外部查询仅返回排名第一的那些 - 即每个实体的版本最高的行。

您也可以添加VALUE1列,例如只是为了显示以前的值:

SELECT ENTITY, VERSION, VALUE1
FROM (
  SELECT ENTITY,
    NVL(LAG(VERSION) OVER (PARTITION BY ENTITY ORDER BY VERSION), VERSION) AS VERSION,
    NVL(LAG(VALUE1) OVER (PARTITION BY ENTITY ORDER BY VERSION), VALUE1) AS VALUE1,
    RANK() OVER (PARTITION BY ENTITY ORDER BY VERSION DESC) AS RN
  FROM MYTABLE
)
WHERE RN = 1
ORDER BY ENTITY;

    ENTITY    VERSION     VALUE1
---------- ---------- ----------
     10000          1         10
     12000          1         50
     14000          2         16