Как обновить существующие записи - PullRequest
0 голосов
/ 10 июня 2018

У меня есть таблица местоположений с иерархией:

Страна> Штат> Город> Сайт

Имя местоположения уникально.Столбец LOCATION2PARENTLOCATION имеет отношение иерархии.

CREATE TABLE "LOCATION" 
   ("LOCATIONID" NUMBER, 
    "NAME" VARCHAR2(50 CHAR), 
    "ALIAS1" VARCHAR2(50 CHAR), 
    "TOWNCITY" VARCHAR2(50 CHAR), 
    "STATE" VARCHAR2(50 CHAR), 
    "COUNTRY" VARCHAR2(50 CHAR), 
    "LOCATION2PARENTLOCATION" NUMBER,
    "LOCATION2LOCATIONTYPE" VARCHAR2(50 CHAR), 
    CONSTRAINT location_id_pk   PRIMARY KEY (LOCATIONID),
    CONSTRAINT location_name_uq UNIQUE(NAME)
   );
INSERT INTO LOCATION VALUES (1,'India',null,null,null,null,null,'COUNTRY');
INSERT INTO LOCATION VALUES (2,'Bihar','BH',null,null,null,1,'STATE');
INSERT INTO LOCATION VALUES (3,'Maharashtra','MH',null,null,null,1,'STATE');
INSERT INTO LOCATION VALUES (4,'Aurangabad',null,null,null,null,2,'CITY');
INSERT INTO LOCATION VALUES (5,'Patna',null,null,null,null,2,'CITY');
INSERT INTO LOCATION VALUES (6,'Pune',null,null,null,null,3,'CITY');
INSERT INTO LOCATION VALUES (8,'Aurangabad,BH',null,null,null,null,2,'CITY');
INSERT INTO LOCATION VALUES (9,'Aurangabad,MH',null,null,null,null,3,'CITY');
INSERT INTO LOCATION VALUES (10,'Deo',null,'Aurangabad','Bihar','India',4,'SITE');
INSERT INTO LOCATION VALUES (11,'Obra',null,'Aurangabad','Bihar','India',4,'SITE');
INSERT INTO LOCATION VALUES (12,'Kutumba',null,'Aurangabad,BH','Bihar','India',8,'SITE');
INSERT INTO LOCATION VALUES (13,'Dura',null,'Aurangabad,BH','Bihar','India',8,'SITE');
INSERT INTO LOCATION VALUES (14,'Dhanpura',null,'Patna','Bihar','India',5,'SITE');
INSERT INTO LOCATION VALUES (15,'Shekhpura',null,'Patna','Bihar','India',5,'SITE');
INSERT INTO LOCATION VALUES (16,'Hadapsar',null,'Pune','Maharashtra','India',6,'SITE');
INSERT INTO LOCATION VALUES (17,'Baner',null,'Pune','Maharashtra','India',6,'SITE');
INSERT INTO LOCATION VALUES (18,'Cidco',null,'Aurangabad,MH','Maharashtra','India',9,'SITE');
INSERT INTO LOCATION VALUES (19,'Mukundwadi',null,'Aurangabad,MH','Maharashtra','India',9,'SITE');

Постановка задачи:

Некоторые названия городов являются общими для нескольких штатов.

Например,,Аурангабад - это город в Махараштре и Бихаре, как и многие другие примеры.Так как имя уникально, поэтому таблица не позволит мне вставить повторяющееся название города в таблицу местоположений с иерархией.

Решение проблемы:

Для поддержания иерархиисреди мест, я решил добавить код штата (Alias1 столбец штата) в название города.Который будет уникальным Именем.

Для.например.

  • Город Патна будет обновлен с помощью 'Patna, BH'
  • Пуна с 'Pune, MH'
  • Аурангабад из Бихара будет обновлен с 'Aurangabad, BH
  • Аурангабад из Махараштры будет обновлен на «Аурангабад, МЗ»

SQL Проблема:

Я хочу обновить все названия городас 'City, StateCode' в старых существующих записях.Но есть некоторые города, уже созданные с «Аурангабадом» и «Аурангабадом, БиГ», оба в одном и том же штате.которые не позволяют мне обновить старую существующую запись.

UPDATE LOCATION L1
SET L1.NAME= L1.NAME ||','||(SELECT L2.ALIAS1 FROM LOCATION L2 WHERE L1.location2parentlocation = L2.LOCATIONID AND L2.location2LOCATIONTYPE='STATE')
WHERE L1.location2locationtype='CITY'
and L1.name not like '%,%';

UPDATE LOCATION L10
SET TOWNCITY= (SELECT NAME FROM LOCATION L11  WHERE L11.LOCATIONID=L10.location2parentlocation AND L11.location2LOCATIONTYPE='CITY')
WHERE L10.LOCATION2LOCATIONTYPE='SITE';


Oracle Error:
SQL Error: ORA-00001: unique constraint (LOCATION_NAME_UQ) violated
00001. 00000 -  "unique constraint (%s.%s) violated"
*Cause:    An UPDATE or INSERT statement attempted to insert a duplicate key.
           For Trusted Oracle configured in DBMS MAC mode, you may see
           this message if a duplicate entry exists at a different level.
*Action:   Either remove the unique restriction or do not insert the key.

Если я удаляю записи с помощью 'City, StateCode', вышеупомянутый оператор обновления будет работать, но я не хочу удалять какую-либо запись.

delete from location where locationid in (8,9,12,13,18,19);
Question:

Как обновить старые существующие записи и поддерживать иерархические отношения.

1 Ответ

0 голосов
/ 10 июня 2018

Но я не хочу удалять какие-либо записи.

Мне кажется, что у вас действительно есть дубликаты данных.LOCATIONID 4 и LOCATIONID 8 действительно представляют один и тот же город, и один из них должен идти.

Если это правильно, сначала необходимо объединить записи SITE для городов 4 и 8 под одним идентификатором.Затем мы можем удалить другой.

Вот оператор MERGE (с комментариями), который делает все это.

Он в основном выясняет, как мы хотим переименовать и перенумеровать города, идентифицируя самый низкий идентификатор города с заданным именем и государством как тот, который мы сохраним.Он объединит записи сайта по городам, которые будут храниться, и удалит города, которые являются дубликатами и больше не нужны.

MERGE INTO location t
USING (
-- This query will list each location along with (for cities and sites) the new city name and city ID to use
WITH city_rename AS (
SELECT city.locationid, 
       city.name city_name, 
       state.name state_name, 
       state.alias1 state_alias1, 
       case when city.name like '%,' || state.alias1 THEN city.name ELSE city.name || ',' || state.alias1 END new_city_name,
       row_number() over ( partition by case when city.name like '%,' || state.alias1 THEN city.name ELSE city.name || ',' || state.alias1 END order by city.locationid ) rn,
       min(city.locationid) over ( partition by case when city.name like '%,' || state.alias1 THEN city.name ELSE city.name || ',' || state.alias1 END order by city.locationid ) new_city_id
FROM   location city
INNER JOIN location state ON state.locationid = city.location2parentlocation
WHERE  city.location2locationtype = 'CITY' )
SELECT l.*, cr.new_city_name, cr.new_city_id FROM location l
LEFT JOIN city_rename cr ON cr.locationid IN (l.locationid, l.location2parentlocation) ) u
ON ( t.locationid = u.locationid )
WHEN MATCHED THEN 
-- Update each CITY and SITE record according to the city renaming results above
UPDATE SET
   -- Rename the city
   t.name = CASE WHEN t.location2locationtype = 'CITY' THEN u.new_city_name ELSE t.name END,
   -- Redirect the sites to the unique city ID for the new city name
   t.location2parentlocation = CASE WHEN t.location2locationtype = 'SITE' THEN u.new_city_id ELSE t.location2parentlocation END,
   -- Rename the towncity for the sites
   t.towncity = CASE WHEN t.location2locationtype = 'SITE' THEN u.new_city_name ELSE t.towncity END
-- Finally, as part of the MERGE, delete any cities that are not unique for the new city name.  Any SITE records 
-- previously tied to this city will have been redirect to the main ID for the new city name by the above logic
DELETE WHERE t.location2locationtype = 'CITY' and u.new_city_id != t.locationid;

После вышеприведенной MERGE ваша таблица LOCATION выглядит следующим образом:

+------------+---------------+--------+---------------+-------------+---------+-------------------------+-----------------------+
| LOCATIONID |     NAME      | ALIAS1 |   TOWNCITY    |    STATE    | COUNTRY | LOCATION2PARENTLOCATION | LOCATION2LOCATIONTYPE |
+------------+---------------+--------+---------------+-------------+---------+-------------------------+-----------------------+
|          1 | India         |  -     |  -            |  -          |  -      |                      -  | COUNTRY               |
|          2 | Bihar         | BH     |  -            |  -          |  -      |                       1 | STATE                 |
|          3 | Maharashtra   | MH     |  -            |  -          |  -      |                       1 | STATE                 |
|          4 | Aurangabad,BH |  -     |  -            |  -          |  -      |                       2 | CITY                  |
|          5 | Patna,BH      |  -     |  -            |  -          |  -      |                       2 | CITY                  |
|          6 | Pune,MH       |  -     |  -            |  -          |  -      |                       3 | CITY                  |
|          9 | Aurangabad,MH |  -     |  -            |  -          |  -      |                       3 | CITY                  |
|         10 | Deo           |  -     | Aurangabad,BH | Bihar       | India   |                       4 | SITE                  |
|         11 | Obra          |  -     | Aurangabad,BH | Bihar       | India   |                       4 | SITE                  |
|         12 | Kutumba       |  -     | Aurangabad,BH | Bihar       | India   |                       4 | SITE                  |
|         13 | Dura          |  -     | Aurangabad,BH | Bihar       | India   |                       4 | SITE                  |
|         14 | Dhanpura      |  -     | Patna,BH      | Bihar       | India   |                       5 | SITE                  |
|         15 | Shekhpura     |  -     | Patna,BH      | Bihar       | India   |                       5 | SITE                  |
|         16 | Hadapsar      |  -     | Pune,MH       | Maharashtra | India   |                       6 | SITE                 |
|         17 | Baner         |  -     | Pune,MH       | Maharashtra | India   |                       6 | SITE                 |
|         18 | Cidco         |  -     | Aurangabad,MH | Maharashtra | India   |                       9 | SITE                 |
|         19 | Mukundwadi    |  -     | Aurangabad,MH | Maharashtra | India   |                       9 | SITE                 |
+------------+---------------+--------+---------------+-------------+---------+-------------------------+-----------------------+

Обратите внимание, как исчез LOCATIONID 8, и все записи, ранее ссылающиеся на него, теперь ссылаются на LOCATIONID 4.

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