2016-10-16 1 views
1

Stellen Sie sich die folgende Tabelle‚Merging‘ mehrere Zeilen mit NULL-Werte in Reihen mit unterschiedlichen Summen

| EEID | CODE1 | VALUE1 | CODE2 | VALUE2 | 
|------|-------|--------|-------|--------| 
| 001 | ABC | 10  | NULL | 0  | 
| 001 | ABC | 5  | NULL | 0  | 
| 001 | DEF | 2  | NULL | 0  | 
| 001 | NULL | 0  | 123 | 3  | 
| 001 | NULL | 0  | 123 | 6  | 
| 001 | NULL | 0  | 456 | 4  | 
| 001 | NULL | 0  | 789 | 1  | 

Der Versuch, herstellerspezifische Funktionen zu vermeiden, was ist der beste Weg, um ‚merge‘ diese SQL wie die aussehen mit nach unten folgende

| EEID | CODE1 | VALUE1 | CODE2 | VALUE2 | 
|------|-------|--------|-------|--------| 
| 001 | ABC | 15  | 123 | 9  | 
| 001 | DEF | 2  | 456 | 4  | 
| 001 | NULL | 0  | 789 | 1  | 

Grundsätzlich muss ich in der Lage sein, die verschiedenen Werte in den CODEx-Spalten zu summieren.

+1

Warum 123 ABC verknüpft ist nicht DEF? –

+0

@MartinSmith es ist nicht erforderlich, dass es explizit mit einer der CODE1-Spalten verknüpft wird. . –

+2

In Ihrem Ergebnis ist es jedoch. Wäre ABC in derselben Ergebniszeile wie 456 und DEF mit 123 gleichwertig? –

Antwort

1

Eine Möglichkeit wäre

SELECT COALESCE(T1.EEID, T2.EEID) AS EEID, 
     CODE1, 
     VALUE1, 
     CODE2, 
     VALUE2 
FROM (SELECT EEID, 
       CODE1, 
       SUM(VALUE1)      AS VALUE1, 
       ROW_NUMBER() OVER (ORDER BY CODE1) AS RN 
     FROM YourTable 
     WHERE CODE1 IS NOT NULL 
     GROUP BY EEID, 
        CODE1) T1 
     FULL JOIN (SELECT EEID, 
         CODE2, 
         SUM(VALUE2)      AS VALUE2, 
         ROW_NUMBER() OVER (ORDER BY CODE2) AS RN 
        FROM YourTable 
        WHERE CODE2 IS NOT NULL 
        GROUP BY EEID, 
          CODE2) T2 
     ON ON T1.RN = T2.RN AND T1.EEID = T2.EEID; 

Es keine herstellerspezifischen Funktionen ist allerdings MySQL um Fensterfunktionen zur Implementierung nicht hat (oder Voll was das betrifft beitreten) noch.

Oder ein anderer Weg.

SELECT EEID, 
     MAX(CODE1) AS CODE1, 
     SUM(VALUE1) AS VALUE1, 
     MAX(CODE2) AS CODE2, 
     SUM(VALUE2) AS VALUE2 
FROM (SELECT EEID, 
       CODE1, 
       VALUE1, 
       CODE2, 
       VALUE2, 
       DENSE_RANK() OVER (PARTITION BY EEID ORDER BY CASE WHEN CODE1 IS NULL THEN 1 ELSE 0 END, Code1) AS RN1, 
       DENSE_RANK() OVER (PARTITION BY EEID ORDER BY CASE WHEN CODE2 IS NULL THEN 1 ELSE 0 END, Code2) AS RN2 
     FROM YourTable) T 
GROUP BY EEID, 
      CASE 
      WHEN CODE1 IS NULL 
       THEN RN2 
      ELSE RN1 
      END 
HAVING COALESCE(MAX(CODE1), MAX(CODE2)) IS NOT NULL; 
+0

Wow, das scheint wirklich gut zu sein und es funktioniert für den Fall von 2 Spalten. –

+0

(wollte nicht Enter drücken) jetzt, wenn Sie eine 3. hinzufügen, und Flip die Case-Anweisungen zu NOT NULLS Ich konnte es für 3 Spalten arbeiten zu bekommen. Das ist toll! Danke! Meine Fensterfunktionsfähigkeiten haben sich verbessert! –

0

Wenn Sie die Werte in den verschiedenen Spalten summieren mögen, würde ich eine andere Ausgangsstruktur vorschlagen:

select eeid, code1, 'code1' as which, sum(value1) 
from t 
where code1 is not null 
group by eeid, code1 
union all 
select eeid, code2, 'code2' as which, sum(value2) 
from t 
where code2 is not null 
group by eeid, code2; 

Diese Werte in verschiedenen Reihen versetzt, aber es ist eine viel einfachere Lösung Ihr Problem.

Dies kann zu einer Dreh erweitert werden, durch group by und row_number() mit:

select eeid, max(code1) as code1, max(value1) as value1, 
     max(code2) as code2, max(value2) as value2 
from ((select eeid, code1, sum(value1) as value1, NULL as code2, NULL as value2, 
       row_number() over (partitionby eeid order by code1) as seqnum 
     from t 
     where code1 is not null 
     group by eeid, code1 
    ) union all 
     (select eeid, NULL, NULL, code2, sum(value2) 
       row_number() over (partition by eeid order by code2) as seqnum 
     from t 
     where code2 is not null 
     group by eeid, code2 
    ) 
    ) t12 
group by eeid, seqnum; 
Verwandte Themen