查找最大的唯一数据集3列的值

时间:2018-12-20 11:08:22

标签: sql oracle

想象下表

  • ID:PrimaryKey(序列生成的数字)
  • ColA:ForeignKey(Number)
  • ColB:ForeignKey(数字)
  • ColC:ForeignKey(数字)
  • 状态:枚举(数字)10、20、30,... 90
  • ValidFrom:TimeStamp(6)
  • 最后更新:(6)

我知道创建了一个查询,以获取处于最高状态(70及更高状态)的任何组合。ColA,ColB和ColC的组合应不存在。如果有一个有效的from可用,则最高者将获胜。如果状态90中有2个,则最新的将获胜:

对于这样的表

|------|------|------|-------|-------------|------------|
| ColA | ColB | ColC | State |ValidFrom    |LastUpdate  |
|------|------|------|-------|-------------|------------|
| 1    | 1    | 1    | 10    |  null       | 10.10.2018 | //Excluded
|------|------|------|-------|-------------|------------|
| 1    | 1    | 1    | 70    |  null       | 09.10.2018 | // lower State
|------|------|------|-------|-------------|------------|
| 1    | 1    | 1    | 90    |  null       | 05.05.2018 | // older LastUpdate
|------|------|------|-------|-------------|------------|
| 1    | 1    | 1    | 90    |  null       | 12.07.2018 | //Should Win
|------|------|------|-------|-------------|------------|
| 1    | 2    | 1    | 90    |  18.10.2018 | 12.07.2018 | //Should Win
|------|------|------|-------|-------------|------------|
| 1    | 2    | 1    | 90    |  null       | 18.11.2018 | //loose against ValidFrom
|------|------|------|-------|-------------|------------|
| 3    | 2    | 1    | 90    |  02.12.2018 | 04.08.2018 | //lower ValidFrom
|------|------|------|-------|-------------|------------|
| 3    | 2    | 1    | 70    |  19.10.2018 | 17.11.2018 | //lower state
|------|------|------|-------|-------------|------------|
| 3    | 2    | 1    | 90    |  18.10.2018 | 14.08.2018 | //Should win
|------|------|------|-------|-------------|------------|

因此,如您所见,ColA,ColB和ColC的组合最后应该是不正确的。

因此,我开始编写脚本,可以为我提供每个组合具有最高状态的所有数据:

   SELECT MAINSELECT.*
FROM
   FOO MAINSELECT
WHERE 
   MAINSELECT.STATE >= 70
AND NOT EXISTS
   (    SELECT SUBSELECT.ID
    FROM 
        FOO SUBSELECT
    WHERE SUBSELECT.ID <> MAINSELECT.ID
       AND SUBSELECT.COLA = MAINSELECT.COLA
       AND SUBSELECT.COLB = MAINSELECT.COLB
       AND SUBSELECT.COLC = MAINSELECT.COLC
       AND SUBSELECT.STATE > MAINSELECT.STATE);

这现在使我所有人处于最高状态。由于我不想使用OR语句,因此尝试解决该问题以在2个不同的查询中使用NULL作为Validfrom或MAX进行查询(并使用并集)。因此,我尝试像这样扩展此基本SELECT,以使用ValidFrom!= null && Max(ValidFrom)获取所有内容:

SELECT MAINSELECT.*
FROM
   FOO MAINSELECT
WHERE 
   MAINSELECT.STATE >= 70
   MAINSELECT.VALIDFROM IS NOT NULL
AND NOT EXISTS
   (    SELECT SUBSELECT.ID
    FROM 
        FOO SUBSELECT
    WHERE SUBSELECT.ID <> MAINSELECT.ID
       AND SUBSELECT.COLA = MAINSELECT.COLA
       AND SUBSELECT.COLB = MAINSELECT.COLB
       AND SUBSELECT.COLC = MAINSELECT.COLC
       AND SUBSELECT.STATE > MAINSELECT.STATE)
AND NOT EXISTS
   (    SELECT SUBSELECT.ID
    FROM 
        FOO SUBSELECT
    WHERE SUBSELECT.ID <> MAINSELECT.ID -- Should not be the same
       AND SUBSELECT.COLA = MAINSELECT.COLA -- Same combination!
       AND SUBSELECT.COLB = MAINSELECT.COLB
       AND SUBSELECT.COLC = MAINSELECT.COLC
       AND SUBSELECT.STATE = MAINSELECT.STATE --Filter on same state!
       AND SUBSELECT.VALIDFROM > MAINSELECT.VALIDFROM);

但这似乎不起作用,因为现在没有任何印刷内容。

我只希望排5和9! [从1开始;-)]

我现在得到第5、7和9行!

因此,组合[3,2,1]是重复的。

我不明白为什么第二个NOT EXISTS不起作用。就像给出了0F ***!

2 个答案:

答案 0 :(得分:0)

使用row_number()

dbfiddle demo

select * 
  from (
    select row_number() over (
                        partition by cola, colb, colc 
                        order by state desc, validfrom desc nulls last, lastupdate desc) rn, 
           foo.*
      from foo)
  where rn = 1

7胜过9,因为2018-12-022018-10-18更新。

说明:

  • partition by cola, colb, colc导致针对这些列的每种组合分别进行编号,
  • 接下来是排序的标准,因此,较高的state获胜,然后是更新的,不可为空的validfrom获胜,最后是更新的lastupdate获胜。

对于a, b, c的每个组合,我们得到一组单独的编号行。外部查询仅过滤编号为1的行。

答案 1 :(得分:0)

我找到了答案。而不是使用NOT EXISTS,我尝试使用max,rpad和Coalesce创建一个要比较的字符串:

for (var c = 0; c < imageSerialNums.length; c++) {
  $("#_cimageType"+ imageSerialNums[c]).rules("add", {
    required : true,
    messages : {}
  });

这将使用STATE,VALIDFROM和LASTUPDATE列中的值创建一个简单的字符串,然后尝试查找其中的最大值!并以人数最多的国家列在最前面!