2017-02-14 14 views
3

Basiert in der Lösung, wenn dieses Problem - Shuffle a column between rows - Ich muss auf diese eine neue Bedingung anwenden: die Namen müssen das Geschlecht garantieren: männlich, weiblich oder unbekannt.Oracle Shuffle Spalten in Zeilen

Also, meine Tabelle haben eine Spalte mit dem Namen gender. Ich muss die Spalten mit dem gleichen Geschlecht mischen.

Ich habe dies versucht, aber in einigen Fällen ich das Geschlecht nicht garantieren kann

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 
; 

Und in Fällen, dass das Geschlecht nicht verfügbar ist (ist Null-Wert), für Namen Beispiel Unternehmen, diese Zusammenführung nichts aktualisieren .

Ich kann diese Abfrage in 3 verschiedenen Merge-Anweisung teilen. Eines für jedes Geschlecht, das ich habe. Aber ich suche nach einer besseren und einfacheren Aussage. Weil ich dieselbe Lösung in einem anderen Kontext und mit anderen Bedingungen anwenden muss. Danke.

EDIT: Beispieldaten

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 

Eine mögliche Lösung:

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

Können Sie eine Probe von Daten zeigen, und gewünschte Ergebnis? –

+1

Beispieldaten hinzugefügt. Ich muss die Namen nach Geschlecht mischen. – milheiros

+0

Ich bin neugierig, warum Sie das tun müssen? – BobC

Antwort

2

Fügen Sie Geschlecht in der PARTITION BY Klausel in den analytischen Funktionen und in der JOIN Klausel. Wenn Sie keinen Primärschlüssel für die Übereinstimmung haben, können Sie die Pseudo-Spalte ROWID verwenden.

Oracle-Setup:

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; 

aktualisieren:

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; 

Ausgang:

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

Tolles MT0! Sie vereinfachen die Lösung! Vielen Dank – milheiros