2017-02-14 32 views
3

Основано на решении, если эта проблема - Shuffle a column between rows - Мне нужно применить к этому новое условие: имена должны гарантировать пол: мужской, женский или неизвестный.Oracle Shuffle столбцов в строках

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

Я попытался это, но в некоторых случаях я не могу гарантировать пол

merge into original_table o 
    using (
    with 
     helper (id, gender, rn, rand_rn) as (
      select id, 
        gender, 
        row_number() over (order by id), 
        row_number() over (order by dbms_random.value()) 
      from original_table 
     ) 
    select ot.name, ot.gender, h2.id 
    from original_table ot inner join helper h1 on (ot.id = h1.id and ot.gender = h1.gender) 
          inner join helper h2 on h1.rand_rn = h2.rn 
) p 
on (o.id = p.id) 
when matched then update set o.name = p.name 
; 

И в тех случаях, что пол не имеется (это нулевое значение), для примера имени компании, это слияние ничего не обновлять ,

Я могу разделить этот запрос на 3 разных оператора слияния. Один для каждого пола, который у меня есть. Но я ищу лучшее и просто заявление. Потому что мне нужно применить одно и то же решение в другом контексте и с разными условиями. Спасибо.

EDIT: Выборочные данные

ID  GENDER NAME                         
3721  M  MARK 
3722  M  JUSTIN 
3723  F  RUTH 
3724  F  MARY 
3725  F  ANNE 
4639    CAMPANY SA                    
4640  M  JOHN 
4641  M  LUCAS 
4642    COMPANY HOLDER SA 

Одно из возможных решений:

ID  GENDER NAME                         
3721  M  LUCAS 
3722  M  JOHN 
3723  F  MARY 
3724  F  ANNE 
3725  F  RUTH 
4639    CAMPANY HOLDER SA                    
4640  M  MARK 
4641  M  JUSTIN 
4642    COMPANY SA 
+0

Можете ли вы показать образец данных и желаемого результата? –

+1

Пример данных. Мне нужно перетасовать имена по полу. – milheiros

+0

Мне любопытно было, зачем вам это нужно? – BobC

ответ

2

Включить пол в предложении PARTITION BY в аналитических функциях и в пункте JOIN. Если у вас нет первичного ключа для сопоставления, вы можете использовать псевдо-столбец ROWID.

Настройка Oracle:

CREATE TABLE original_table (id, gender, name, company) AS 
SELECT 1, 'F', 'Alice', CAST(NULL AS VARCHAR2(20)) FROM DUAL UNION ALL 
SELECT 2, 'M', 'Bobby', 'ACME' FROM DUAL UNION ALL 
SELECT 3, 'F', 'Carol', 'XYZ' FROM DUAL UNION ALL 
SELECT 4, 'M', 'David', NULL FROM DUAL UNION ALL 
SELECT 5, 'M', 'Errol', 'ACME' FROM DUAL UNION ALL 
SELECT 6, 'F', 'Fiona', 'XYZ' FROM DUAL; 

Update:

MERGE INTO original_table dst 
USING (
    WITH rnd (rid, rn, rnd_rn, gender, name) AS (
    SELECT ROWID, 
      ROW_NUMBER() OVER (PARTITION BY gender ORDER BY id), 
      ROW_NUMBER() OVER (PARTITION BY gender ORDER BY DBMS_RANDOM.VALUE), 
      gender, 
      name 
    FROM original_table 
) 
    SELECT o.rid, r.name 
    FROM rnd o INNER JOIN rnd r 
     ON ((o.gender = r.gender OR (o.gender IS NULL AND r.gender IS NULL)) 
      AND o.rn = r.rnd_rn) 
) 
ON (dst.ROWID = src.ROWID) 
WHEN MATCHED THEN 
    UPDATE SET name = src.name; 

Выход:

SELECT * FROM original_table; 

ID G NAME COMPANY 
-- - ----- ------- 
1 F Fiona 
2 M David ACME 
3 F Alice XYZ 
4 M Bobby 
5 M Errol ACME 
6 F Carol XYZ 
+0

Отличный MT0! Вы упрощаете решение! благодаря – milheiros