Использование Join в запросе на удаление - PullRequest
0 голосов
/ 10 мая 2018

Мне нужно написать запрос, чтобы удалить дубликаты активных записей из таблицы.Вот примерный набор строк из таблицы.

select * from balance where ACCOUNT = '832076635';

ACCOUNT    BALANCE_AMT  TIMESTAMP  ACTIVE    
832076635  10.23        02-MAR-18  1   
832076635  13.34        29-DEC-17  1
832076635  9.22         01-OCT-17  0

Я должен удалить строку с max (timestamp) с active = 1. Таких строк может быть несколько.Я попробовал приведенный ниже запрос, но он не работает.Может ли кто-нибудь, пожалуйста, помогите.

WITH TMP AS
  (select account, max(timestamp) AS MAXTIME from balance 
   where active = 1 group by account   having count(*) > 1)
delete from balance b 
  INNER JOIN TMP t
  ON (b.account = t.account
     AND b.timestamp = t.MAXTIME)

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

Oracle не поддерживает общие табличные выражения или объединения ни в чем, кроме оператора SELECT, но вы можете использовать коррелированный подзапрос для выполнения той же работы:

DELETE FROM BALANCE b
  WHERE EXISTS (SELECT t.ACCOUNT, MAX(t.TIMESTAMP)
                  FROM BALANCE t
                  WHERE t.ACTIVE = 1
                  GROUP BY t.ACCOUNT
                  HAVING COUNT(*) > 1 AND
                         t.ACCOUNT = b.ACCOUNT AND
                         MAX(t.TIMESTAMP) = b.TIMESTAMP AND
                         b.ACTIVE = 1);

Кроме того, я предлагаю вам не делатьt использовать зарезервированные слова, такие как TIMESTAMP, в качестве имени столбца.Это в конечном итоге укусит вас.

Удачи.

0 голосов
/ 10 мая 2018

Вы можете использовать оператор MERGE, чтобы удалить все повторяющиеся строки, кроме самой старой:

SQL Fiddle

Настройка схемы Oracle 11g R2 :

CREATE TABLE balance ( account, timestamp, active ) AS
SELECT 832076635, DATE '2018-03-02', 1 FROM DUAL UNION ALL
SELECT 832076635, DATE '2017-12-29', 1 FROM DUAL UNION ALL
SELECT 832076635, DATE '2017-10-01', 0 FROM DUAL;

Запрос 1 :

MERGE INTO balance src
USING (
  SELECT RID
  FROM   (
    SELECT ROWID AS rid,
           ROW_NUMBER() OVER ( PARTITION BY account ORDER BY timestamp ASC ) AS rn
    FROM   balance
    WHERE  active = 1
  )
  WHERE rn > 1
) dst
ON ( src.ROWID = dst.RID )
WHEN MATCHED THEN
  UPDATE SET active = 1
  DELETE WHERE 1 = 1

Запрос 2 :

SELECT * FROM BALANCE

Результаты

|   ACCOUNT |            TIMESTAMP | ACTIVE |
|-----------|----------------------|--------|
| 832076635 | 2017-12-29T00:00:00Z |      1 |
| 832076635 | 2017-10-01T00:00:00Z |      0 |

Или просто удалите самый новый активный дубликат:

MERGE INTO balance src
USING (
  SELECT RID
  FROM   (
    SELECT ROWID AS rid,
           ROW_NUMBER() OVER ( PARTITION BY account ORDER BY timestamp DESC ) AS rn,
           COUNT(*) OVER ( PARTITION BY account ) AS ct
    FROM   balance
    WHERE  active = 1
  )
  WHERE rn = 1 AND ct > 1
) dst
ON ( src.ROWID = dst.RID )
WHEN MATCHED THEN
  UPDATE SET active = 1
  DELETE WHERE 1 = 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...