2016-03-25 14 views
1

Ich habe eine große Tabelle mit Tonnen von doppelten Zeilen (unter den Spalten, die mir wichtig sind). Lassen Sie mich mit dem folgenden Beispiel beginnen:SQL-Gruppe von unter bestimmten Bedingungen

|field1 | field2| field3| field4| field5| 
| aa | 1  | NULL | 1  | 0  | 
| aaa | 1  | NULL | 1  | 1  | 
| aaa | 1  | NULL | 1  | 2  | 
| a  | 2  | 0  | 1  | 3  | 
| a  | 2  | 0  | NULL | 4  | 
| a  | 2  | NULL | 2  | 5  | 
| b  | 3  | NULL | 2  | 6  | 
| b2 | 3  | NULL | NULL | 7  | 
| c  | 4  | NULL | NULL | 8  | 

Ich interessiere mich für eine effiecient Abfrage in der folgenden Tabelle zu erhalten:

|field1 | field2| field3| field4| 
| aaa | 1  | NULL | 1  | 
| a  | 2  | 0  | 1  | 
| b  | 3  | NULL | 2  | 
| c  | 4  | NULL | NULL | 

Grundsätzlich folgt die folgenden Regeln:

  1. für Jeder Wert von Feld2, es sollte eine und genau eine Zeile vorhanden sein
  2. unter allen Zeilen mit dem gleichen Wert von Feld2 wählen Sie die Zeile, die th erfüllen e folgend in der Reihenfolge:
    • die Zeile auszuwählen, dass Field4 nicht Null ist (wenn möglich)
    • unter denjenigen, die einen nicht Null-Wert haben, für die die Zeilen Field4 auswählen, die einen nicht Null-Wert für das Feld hat 3
    • unter denen, die einen Nicht-Null-Wert für das Feld4 und 3 haben, wählen Sie die Zeile mit dem längsten Zeichenfolgenwert für Feld 1
    • unter denen, die alle oben genügen, wählen Sie nur eine Zeile (egal was ist der Wert von field5).

ich es mit Bündel verbindet, tun könnte, aber es wird sehr langsam. Irgendwelche besseren Vorschläge?

EDIT Die field2 Werte können nicht in einer bestimmten Reihenfolge. Ich habe im Beispiel nur 1,2,3,4 eingegeben, aber das trifft in meinem Fall nicht zu. Ich habe es nicht direkt auf dem Tisch geändert, da eine der vorgeschlagenen Lösungen tatsächlich den sequentiellen Wert für field2 berücksichtigt, also behielt ich für zukünftige Leser, die vielleicht daran interessiert sind.

Antwort

2

Diese Art der Priorisierung ist eine Herausforderung. Ich denke, die einfachste Methode in MySQL Variablen verwendet:

select t.* 
from (select t.*, 
      (@rn := if(@f2 = field2, @rn + 1, 
         if(@f2 := field2, 1, 1) 
         ) 
      ) as seqnum 
     from t cross join 
      (select @rn := 0, @field2 := '') params 
     order by field2, 
       (field4 is not null) desc, 
       (field3 is not null) desc, 
       length(field1) desc 
    ) t 
where seqnum = 1; 

ich nicht 100% sicher bin ich die Bedingungen haben Recht (die dritte scheint mit den ersten beiden in Konflikt). Unabhängig von der Priorisierung ist die Idee die gleiche: Verwenden Sie order by, um die Zeilen in die richtige Reihenfolge zu bringen, und verwenden Sie Variablen, um die erste zu erhalten.

EDIT:

In SQL Server - oder jede andere vernünftige Datenbank - Sie tun dies mit row_number():

select t.* 
from (select t.*, 
      row_number() over (partition by field2 
           order by (case when field4 is not null then 0 else 1 end), 
             (case when field3 is not null then 0 else 1 end), 
             len(field1) 
           ) as seqnum 
     from t 
    ) t 
where seqnum = 1; 
+0

Dank Gordon, ich meinte Feld 4 nicht Null es war ein Tippfehler zu sein, Ich habe es in der Frage behoben. Lass mich deinen Vorschlag ausprobieren. – Amin

+0

Gordon, Field2 ist möglicherweise nicht sequenziell. Mein Fehler, es in einer Sequenz im Beispiel zu machen. Sie sind eigentlich völlig zufällige Werte. Irgendwelche Vorschläge in dieser Situation? – Amin

+0

@Amin. . . Das macht keinen Unterschied zu den Bedingungen, die Sie beschreiben. –

Verwandte Themen