Найти уникальный набор данных с макс.значение из 3 столбцов - PullRequest
0 голосов
/ 20 декабря 2018

Отображение следующей таблицы

  • ID: PrimaryKey (номер, сгенерированный последовательностью)
  • ColA: ForeignKey (число)
  • ColB: ForeignKey (число)
  • ColC: ForeignKey (Число)
  • Состояние: перечисление (Число) 10,20,30, ... 90
  • ValidFrom: TimeStamp (6)
  • LastUpdate: (6)

Я знаю, что создал запрос для извлечения любой комбинации в наивысших состояниях (70 и выше). Комбинация ColA, ColB и ColC должна быть необязательной.Если есть действительный из доступных, победит самый высокий.Если в состоянии 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, я попытался решить проблему, чтобы запросить NULL как Validfrom или MAX в 2 разных запросах (и использовать объединение).Поэтому я попытался расширить этот базовый 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] является дубликатом.

Не понимаю, почему 2-е НЕ СУЩЕСТВУЕТ не работает.Это как дано 0F *** дано!

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

Я нашел ответ.Вместо использования NOT EXISTS я пытаюсь использовать max, rpad и coalesce для создания строки, которую я сравниваю:

SELECT 
    MAINSELECT.*
FROM 
    FOO MAINSELECT
WHERE (1 = 1)
    AND MAINSELECT.STATE >= 70
    AND coalesce(to_char(MAINSELECT.state), rpad('0', 3, '0') ) || coalesce(to_char(MAINSELECT.validfrom,'YYMMDDhh24missFF'), rpad('0', 18, '0') ) || coalesce(to_char(MAINSELECT.lastupdate,'YYMMDDhh24missFF'), rpad('0', 18, '0') )
    = (select max(coalesce(to_char(SUBSELECT.state), rpad('0', 3, '0') ) || coalesce(to_char(SUBSELECT.validfrom,'YYMMDDhh24missFF'), rpad('0', 18, '0') )|| coalesce(to_char(SUBSELECT.lastupdate,'YYMMDDhh24missFF'), rpad('0', 18, '0')))                
        FROM 
            FOO SUBSELECT
        WHERE (1 = 1)
            AND SUBSELECT.STATE >= 70
            AND SUBSELECT.COLA = MAINSELECT.COLA
            AND SUBSELECT.COLB = MAINSELECT.COLB
            AND SUBSELECT.COLC = MAINSELECT.COLC
  );

Это создает простую строку со значениями из столбцов STATE, VALIDFROM и LASTUPDATE изатем пытается найти максимум из них!заявляя с государством, которое имеет наибольшее число и идет впереди!

0 голосов
/ 20 декабря 2018

Использование row_number():

Демоверсия dbfiddle

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-02 новее, чем 2018-10-18.

Объяснение:

  • partition by cola, colb, colc приводит к тому, что для каждой комбинации этих столбцов нумерация выполняется отдельно,
  • далее идут критерии упорядочения, поэтому выше state выигрышей, затем новее, не обнуляется validfrom выигрышей, а в конце более новые lastupdate выигрышей.

за каждую комбинацию a, b, cмы получаем отдельный набор пронумерованных строк.Внешние запросы фильтруют только строки, пронумерованные как 1.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...