2009-06-01 6 views
6

Ich habe diese Anfrage:Faster 'select distinct thing_id, thing_name von table1' in oracle

select distinct id,name from table1 

Für eine bestimmte ID, wird der Name immer gleich sein. Beide Felder sind indiziert. Es gibt keine separate Tabelle, die die ID dem Namen zuordnet. Die Tabelle ist sehr groß (10 Millionen Zeilen), daher könnte die Abfrage einige Zeit dauern.

Diese Abfrage ist sehr schnell, da es indiziert ist:

select distinct name from table1 

Ebenso für diese Abfrage:

select distinct id from table1 

Angenommen, ich kann nicht die Datenbankstruktur (eine sehr sichere Annahme) umziehen, was eine bessere Möglichkeit, die erste Abfrage für die Leistung zu strukturieren?

bearbeiten eine hygienisiert ab der Tabelle hinzuzufügen:

 

Name       Null  Type 
------------------------------ -------- ---------------------------- 
KEY       NOT NULL NUMBER 
COL1       NOT NULL NUMBER 
COL2       NOT NULL VARCHAR2(4000 CHAR) 
COL3       VARCHAR2(1000 CHAR) 
COL4       VARCHAR2(4000 CHAR) 
COL5       VARCHAR2(60 CHAR) 
COL6       VARCHAR2(150 CHAR) 
COL7       VARCHAR2(50 CHAR) 
COL8       VARCHAR2(3 CHAR) 
COL9       VARCHAR2(3 CHAR) 
COLA       VARCHAR2(50 CHAR) 
COLB       NOT NULL DATE 
COLC       NOT NULL DATE 
COLD       NOT NULL VARCHAR2(1 CHAR) 
COLE       NOT NULL NUMBER 
COLF       NOT NULL NUMBER 
COLG       VARCHAR2(600 CHAR) 
ID        NUMBER 
NAME       VARCHAR2(50 CHAR) 
COLH       VARCHAR2(3 CHAR) 

20 rows selected 
+0

Könnten Sie möglicherweise eine WHERE-Klausel hinzufügen, um Ihre Ergebnismenge schnell einzugrenzen? Ich bin mir nicht sicher, ob Sie das schon tun, obwohl die gezeigten Beispiele keine Prädikatenlogik haben. :) – tom

+0

Wie viele Zeilen werden von DISTINCT ID und DISTINCT NAME zurückgegeben? – Quassnoi

+0

33 Reihen für jeden. –

Antwort

12

[AKTUELLE EDIT]

Meine ORIGINAL ANTWORT in Bezug auf den entsprechenden Index erstellen auf (Name, ID), den Index ersetzen auf (Name) ist unten. (Das war keine Antwort auf die ursprüngliche Frage, die Datenbankänderungen nicht zuließ.)

Hier sind Aussagen, die ich nicht noch getestet habe. Es gibt wahrscheinlich einen offensichtlichen Grund, warum das nicht funktionieren wird. Ich würde nie wirklich vorschlagen Schreiben Aussagen wie diese (auf die Gefahr für eine solche lächerlichen Vorschlag gründlich getrommelt werden.)

Wenn diese Abfragen auch Ergebnismengen zurückgeben, die ressult Satz enthält nur das Ergebnis ähnlich aus dem OP eingestellt Abfrage, fast durch Zufall, unter Ausnutzung einer schrulligen Garantie über die Daten, die Don uns zur Verfügung gestellt hat. Diese Anweisung entspricht NICHT dem ursprünglichen SQL. Diese Anweisungen sind für den von Don beschriebenen Sonderfall ausgelegt.

select m1.id 
     , m2.name 
    from (select min(t1.rowid) as min_rowid 
       , t1.id 
      from table1 t1 
      where t1.id is not null 
      group by t1.id 
     ) m1 
     , (select min(t2.rowid) as min_rowid 
      , t2.name from table1 t2 
     where t2.name is not null 
     group by t2.name 
     ) m2 
    where m1.min_rowid = m2.min_rowid 
    order 
    by m1.id 

Lassen Sie uns das auspacken:

  • m1 ist ein Inline-Ansicht, die uns eine Liste von unterschiedlichen ID-Werte erhält.
  • m2 ist eine Inline-Ansicht, die uns eine Liste der eindeutigen Namen Werte erhält.
  • materialisieren die Ansichten m1 und m2
  • Spiel der ROWID von m1 und m2id mit name

jemand anderes die Idee eines Index merge vorgeschlagen übereinstimmen. Ich hatte zuvor diese Idee, einen Optimierer Plan, um 10 Millionen von rowids übereinstimmen, ohne sie zu beseitigen.

mit ausreichend niedrigen Kardinalität für ID und Namen, und mit dem richtigen Optimierungsprogramm Plan:

select m1.id 
     , (select m2.name 
      from table1 m2 
      where m2.id = m1.id 
      and rownum = 1 
     ) as name 
    from (select t1.id 
      from table1 t1 
      where t1.id is not null 
      group by t1.id 
     ) m1 
    order 
    by m1.id 

sie auspacken, dass

  • m1 ist eine Inline-Ansicht, die uns eine Liste von verschiedenen bekommt ID-Werte.
  • materialisieren die Ansicht m1
  • für jede Zeile in m1, Abfrage tabelle1 den Namen Wert aus einer einzelnen Zeile (stopkey)

WICHTIGER HINWEIS

Diese Aussagen zu erhalten sind grundsätzlich anders als die OP-Abfrage. Sie sind so konzipiert, dass sie ein UNTERSCHIEDLICHES Ergebnis als die OP-Abfrage zurückgeben. Die passieren, um die gewünschte Ergebnismenge wegen einer eigenartigen Garantie über die Daten zurückzugeben. Don hat uns gesagt, dass name durch id bestimmt wird. (Ist das Gegenteil wahr? Ist id von name bestimmt? Haben wir eine garantierte Garantie, nicht unbedingt durch die Datenbank durchgesetzt, aber eine Garantie, die wir nutzen können?) Für jede ID Wert wird jede Zeile mit diesem ID Wert haben das gleiche NAME Wert. (Und wir werden garantiert auch das Gegenteil wahr ist, dass für jeden NAME Wert, jede Zeile mit diesem Wert NAME den gleichen ID Wert?)

Wenn ja, vielleicht können wir Verwendung dieser Informationen machen. Wenn ID und NAME in verschiedenen Paaren auftreten, müssen wir nur eine bestimmte Zeile finden. Das "Paar" wird eine passende ROWID haben, die zufällig von jedem der vorhandenen Indizes verfügbar ist. Was ist, wenn wir für jede ID die minimale ROWID erhalten und für jede NAME die minimale ROWID erhalten. Könnten wir nicht die ID mit der NAME basierend auf der ROWID, die das Paar enthält, übereinstimmen? Ich denke, dass es funktionieren könnte, wenn eine Kardinalität niedrig genug ist. (Das heißt, wenn wir mit nur tun sind Hunderte von ROWIDs anstatt 10s von Millionen.)

[/ AKTUELLE EDIT]

[EDIT]

Die Frage ist nun mit Informationen über die aktualisierte Tabelle zeigt, dass die ID Spalte und die NAME Spalte beide NULL-Werte zulassen. Wenn Don ohne NULL-Werte leben kann, die in der Ergebnismenge zurückgegeben werden, kann das Hinzufügen des IS NOT NULL-Prädikats für diese beiden Spalten die Verwendung eines Indexes ermöglichen. (HINWEIS: In einem Oracle-Index (B-Tree) erscheinen NULL-Werte NICHT im Index.)

[/ EDIT]

ORIGINAL ANTWORT:

einen entsprechenden Index

create index table1_ix3 on table_1 (name,id) ... ; 

Ordnung schaffen, das ist nicht die Antwort auf die Frage, die Sie gefragt, aber es ist die richtige Antwort auf die Behebung des Leistungsproblems. (Sie haben keine Änderungen an der Datenbank angegeben, aber in diesem Fall ist das Ändern der Datenbank die richtige Antwort.)

Beachten Sie, dass Sie (sehr wahrscheinlich) keinen Index benötigen, wenn Sie einen Index für (name,id) definiert haben unter (name), wird der Optimierer die führende Spalte name im anderen Index berücksichtigen.

(UPDATE: als jemand klüger als ich darauf hinwies, hatte ich nicht einmal die Möglichkeit in Betracht gezogen, dass die vorhandenen Indizes Bitmap-Indizes und nicht die B-Tree-Indizes waren ...)


Re- Bewerten Sie Ihren Bedarf für die Ergebnismenge ... müssen Sie id zurückgeben, oder würde name ausreichend sein.

select distinct name from table1 order by name; 

Für einen bestimmten Namen, können Sie eine zweite Abfrage senden die zugehörige id zu bekommen, ob und wann Sie es benötigt ...

select id from table1 where name = :b1 and rownum = 1; 

Wenn Sie Sie wirklich Notwendigkeit In der angegebenen Ergebnismenge können Sie einige Alternativen ausprobieren, um zu sehen, ob die Leistung besser ist. Ich halte nicht viel Hoffnung für eine dieser aus:

select /*+ FIRST_ROWS */ DISTINCT id, name from table1 order by id; 

oder

select /*+ FIRST_ROWS */ id, name from table1 group by id, name order by name; 

oder

select /*+ INDEX(table1) */ id, min(name) from table1 group by id order by id; 

UPDATE: wie andere astutely darauf hingewiesen haben, mit diesem Ansatz wir Erneutes Testen und Vergleichen der Leistung alternativer Abfragen, was eine Art "hit or miss" -Ansatz ist. (Ich stimme nicht zu, dass es zufällig ist, aber ich würde zustimmen, dass es Hit oder Fräulein ist).

UPDATE: tom schlägt den ALL_ROWS Hinweis vor. Ich hatte das nicht berücksichtigt, weil ich mich wirklich darauf konzentrierte, einen Abfrageplan mit einem INDEX zu erstellen. Ich vermute, dass die OP-Abfrage eine vollständige Tabelle scannen, und es ist wahrscheinlich nicht der Scan, der die Zeit nimmt, es ist die Art einzigartige Operation (< 10g) oder Hash-Operation (10gR2 +), die die Zeit braucht. (Abgesagte Zeitstatistiken und Ereignis 10046 Trace, ich rate nur hier.) Aber andererseits, vielleicht ist es der Scan, wer weiß, der High Watermark auf dem Tisch könnte weit draußen in einer Weite von leeren Blöcken sein.

Es ist fast selbstverständlich, dass die Statistiken in der Tabelle auf dem neuesten Stand sein sollten, und wir sollten SQL * Plus AUTOTRACE oder zumindest EXPLAIN PLAN verwenden, um die Abfragepläne zu betrachten.

Aber keiner der vorgeschlagenen alternativen Abfragen behandelt wirklich das Leistungsproblem.

Es ist möglich, dass Hinweise den Optimierer beeinflussen, um einen anderen Plan zu choozen, grundsätzlich die ORDER BY aus einem Index erfüllend, aber ich hege keine großen Hoffnungen dafür. (Ich glaube nicht, dass der FIRST_ROWS-Hinweis mit GROUP BY funktioniert, der INDEX-Hinweis könnte dazu führen.) Ich kann das Potenzial für einen solchen Ansatz in einem Szenario sehen, in dem Datenblöcke leer und dünn besetzt sind und auf die Daten zugegriffen wird Blöcke über einen Index, es könnten tatsächlich wesentlich weniger Datenblöcke in den Speicher gezogen werden ... aber dieses Szenario wäre eher die Ausnahme als die Norm.


UPDATE: Als Rob van Wijk weist darauf hin, die Nutzung der Oracle Trace-Einrichtung ist der effektivste Ansatz zur Identifizierung und Performance-Probleme zu lösen.

Ohne die Ausgabe eines EXPLAIN PLAN oder SQL * Plus AUTOTRACE-Ausgabe, rate ich hier nur.

Ich vermute, das Leistungsproblem, das Sie gerade haben, ist, dass die Tabellendatenblöcke referenziert werden müssen, um die angegebene Ergebnismenge zu erhalten.

keine Es gibt um es bekommt, kann die Abfrage nicht aus nur einem Index zufrieden sein, da es nicht ein Index ist, der enthält sowohl die NAME und ID Spalten, entweder mit den ID oder NAME Spalt als die führenden Spalte. Die anderen zwei "schnellen" OP-Abfragen können aus dem Index befriedigt werden, ohne dass auf die Zeile Bezug genommen werden muss (Datenblöcke).

Auch wenn der Optimierungsplan für die Abfrage einen der Indizes verwendet, muss er dennoch die zugehörige Zeile aus dem Datenblock abrufen, um den Wert für die andere Spalte zu erhalten. Und ohne Prädikat (keine WHERE-Klausel) entscheidet sich der Optimierer wahrscheinlich für einen vollständigen Tabellenscan und wahrscheinlich für eine Sortieroperation (< 10g). (Auch hier würde ein EXPLAIN-Plan den Optimierungsplan anzeigen, genauso wie AUTOTRACE.)

Ich nehme auch hier an (große Annahme), dass beide Spalten als NOT NULL definiert sind.

Sie können auch die Tabelle als organisierte Indextabelle (IOT) definieren, insbesondere wenn dies die einzigen beiden Spalten in der Tabelle sind. (Ein IOT ist kein Allheilmittel, es kommt mit einem eigenen Satz von Leistungsproblemen.)


Sie können versuchen, das Neuschreiben der Abfrage (es sei denn, das ist eine Datenbankänderung, die auch verboten ist) In unserer Datenbank Umgebungen betrachten wir eine Abfrage als einen Teil der Datenbank als die Tabellen und Indizes.)

Auch hier wird der Optimierer ohne Prädikat wahrscheinlich keinen Index verwenden. Es gibt eine Chance, dass Sie den Abfrage-Plan eine der vorhandenen Indizes verwenden, erhalten konnten die ersten Reihen schnell zurück zu bekommen, durch einen Hinweis hinzufügen, testen eine Kombination aus:

select /*+ INDEX(table1) */ ... 
select /*+ FIRST_ROWS */ ... 
select /*+ ALL_ROWS */ ... 

    distinct id, name from table1; 
    distinct id, name from table1 order by id; 
    distinct id, name from table1 order by name; 
    id, name from table1 group by id, name order by id; 
    id, min(name) from table1 group by id order by id; 
    min(id), name from table1 group by name order by name; 

Mit einem Hinweis, können Sie möglicherweise zu Beeinflussen Sie den Optimierer, einen Index zu verwenden, und das kann die Sortieroperation vermeiden, aber insgesamt dauert es länger, bis die gesamte Ergebnismenge zurückgegeben wird.

(UPDATE: jemand anders wies darauf hin, dass der Optimierer möglicherweise zwei Indizes basierend auf ROWID zusammenführen würde.Das ist eine Möglichkeit, aber ohne ein Prädikat, um einige Zeilen zu eliminieren, wird das wahrscheinlich ein viel teurerer Ansatz sein (Übereinstimmung von 10 Millionen ROWIDs) aus zwei Indizes, insbesondere wenn keine der Zeilen auf der Grundlage der ausgeschlossen werden match.)

Aber alles, was theoretisieren ist nicht auf Kniebeugen ohne einige Leistungsstatistiken.


Abwesend irgendetwas anderes in der Datenbank zu verändern, die einzige andere Hoffnung (ich mich vorstellen kann) von der Abfrage zu beschleunigen ist der Sortiervorgang, um sicherzustellen, abgestimmt ist, so dass der (erforderlich) Sortiervorgang sein kann im Speicher ausgeführt, anstatt auf der Festplatte. Aber das ist nicht wirklich die richtige Antwort. Der Optimierer führt möglicherweise überhaupt keine Sortieroperation durch, sondern führt stattdessen eine Hash-Operation (10gR2 +) durch, in diesem Fall sollte diese optimiert werden. Der Sortiervorgang ist nur eine Vermutung meinerseits, basierend auf den Erfahrungen der Vergangenheit mit Oracle 7.3, 8, 8i, 9i.)

Eine ernsthafte DBA mehr Problem wird sich mit Ihnen mit dem SORT_AREA_SIZE futzing und/oder HASH_AREA_SIZE Parameter für Ihre Sitzung (en) als beim Erstellen der richtigen Indizes. (Und diese Session-Parameter sind "Old School" für Versionen vor 10g automatische Speicherverwaltung magic.)

Zeigen Sie Ihrem DBA die Spezifikation für die Ergebnismenge, lassen Sie den DBA tune es.

+0

Ja, das sind Spalten, keine Felder. Beachten Sie auch, dass 'Index erstellen' eine Datenbankänderung darstellt. –

+0

@Don, ja, der 'create index' ist eine Datenbankänderung. Sie haben die falschen Indizes definiert. Der Index für (name) sollte durch einen Index für (name, id) ersetzt werden. Das ist die richtige Antwort. – spencer7593

+0

"Angenommen, ich kann nicht die Datenbankstruktur geändert werden" ist ein Schlüsselelement der Frage, die ich gestellt habe. Alle Ihre Informationen sind gut, es ist einfach nicht in meinem Kontext. –

0

Sie konnten dieses versuchen:

select id, max(name) from table1 group by id 

Dieses verwendet den Index auf id sicher, aber Sie müssen versuchen, wenn es schnell durchführt. Indem sie aus unerklärlichen Gründen schneller als ein DISTINCT

select id, name from table1 group by id, name 

ich vage Erinnerungen an eine GROUP haben:

+0

Ich habe es gerade versucht. Es ist aber immer noch langsam. –

0

Ohne die in der Praxis frönen zu wollen Sachen an die Wand, bis etwas Sticks zu werfen, versuchen Sie dies.

+0

Sorry, es hat nicht gehalten. Danke trotzdem, es war einen Versuch wert. –

+0

Das stimmt. Das Schlüsselwort DISTINCT gruppiert nicht nur, sondern ordnet auch die Ergebnisse an. – tom

+0

DISTINCT ist nicht immer ORDER BY in 10g aufwärts – cagcowboy

0

Warum brauchen Sie "name" in der Klausel, wenn der Name für eine bestimmte ID immer gleich ist? (Nm ... Sie wollen den Namen, den Sie gerade nicht auf die Existenz Überprüfung)

SELECT name, id FROM table WHERE id in (SELECT DISTINCT id FROM table)? 

Sie wissen nicht, ob das hilft ...

+0

Um den Namen dem Benutzer anzuzeigen. –

+0

Ja, ich dachte mir das und fügte hinzu, dass in Parens ... – GreenieMeanie

0

Ist id einzigartig? Wenn ja, könnten Sie DISTINCT aus der Abfrage löschen. Wenn nicht - vielleicht braucht es einen neuen Namen? Ja, ich weiß, kann nicht das Schema ändern ...

+0

Es ist nicht einzigartig. Es wird eine große Anzahl von Zeilen geben, die alle dieselbe ID und denselben Namen haben, und ich versuche, die Liste zu bekommen. Wenn da etwas wie select first.id, first.name wäre, würde das wohl ausreichen. –

+0

Du meinst wie, SELECT ID, Name FROM Tabelle WHERE rownum = 1? – tom

+0

gut, außer ich möchte eine von jeder ID, nicht nur eine insgesamt –

0

Sie etwas versuchen könnten, wie

Select Distinct t1.id, t2.name 
FROM (Select Distinct ID From Table) As T1 
INNER JOIN table t2 on t1.id=t2.id 

Select distinct t1.id, t2.name from table t1 
inner Join table t2 on t1.id=t2.id 

Nicht sicher, ob dies funktioniert langsamer oder schneller als das Original, da ich nicht ganz verstehen bin wie dein Tisch aufgebaut ist. Wenn jede ID immer den gleichen Namen hat und die ID eindeutig ist, sehe ich nicht wirklich den Unterschied.

+0

Viele Zeilen haben die gleiche ID, aber eine gegebene ID wird immer mit dem gleichen Namen gepaart. –

2

Eine Abfrage kann nicht gestimmt werden, indem man sie anschaut oder zufällig einige gleichwertige Abfragen vorschlägt, unabhängig davon, wie gut sie gemeint sind.

Sie, wir oder der Optimierer müssen Statistiken über Ihre Daten kennen. Und dann können Sie mit Tools wie EXPLAIN PLAN oder SQL Trace/tkprof oder sogar das einfache Autotrace-Tool von SQL Plus messen.

Können Sie uns zeigen den Ausgang dieses:

set serveroutput off 
select /*+ gather_plan_statistics */ distinct id,name from table1; 
select * from table(dbms_xplan.display_cursor(null,null,'allstats last')); 

Und wie sieht Ihre gesamte tabelle1 aussehen? Bitte zeigen Sie eine Beschreibung an.

Grüße, Rob.

+0

+1 @Rob van Wijk: ausgezeichnete Punkte.Die Oracle-Einrichtung ermöglicht uns Einblicke in Leistungsprobleme, insbesondere die Verfolgung des Ereignisses 10046 für Wartestatus und des Ereignisses 10053 für den Optimierungsplan. Aber nur eine Anmerkung, einige der Tuning-Hilfsmittel, die ich tatsächlich _do_ verwendet habe alternative Abfragen (ableti nicht zufällig, aber systematisch) zum Beispiel IN-Prädikate mit EXISTS-Prädikaten ersetzen, DISTINCT durch GROUP BY-Klausel ersetzen, Hinweise hinzufügen und dann ausführen die alternativen Abfragen, um die Leistung zu vergleichen. – spencer7593

+0

Ich habe den Satz von drei Abfragen mit Oracle SQL Developer ausgeführt, und es gibt keine Ausgabe. Vielleicht steht dieses Werkzeug im Weg. Was die zweite betrifft, füge ich eine bereinigte Version hinzu. Ich muss nur die Felder umbenennen. –

+0

Bitte versuchen Sie SQL * Plus (in Ihrem bin-Ordner gefunden) –

0

"Die Tabelle ist sehr groß (10 Millionen Zeilen)" Wenn Sie die Datenbank nicht ändern können (Index usw. hinzufügen). Dann hat Ihre Abfrage keine andere Wahl, als die gesamte Tabelle zu lesen. Bestimmen Sie zunächst, wie lange das dauert (dh die SELECT ID, NAME FROM TABLE1). Sie werden es nicht schneller als das bekommen. Der zweite Schritt ist der DISTINCT. In 10g + sollte eine HASH GROUP BY verwendet werden. Zuvor ist es eine SORT-Operation. Ersteres ist schneller. Wenn Ihre Datenbank 9i ist, dann können Sie eine Verbesserung erhalten, indem Sie die 10 Millionen Zeilen in eine 10g-Datenbank kopieren und dort tun. Alternativ können Sie Speicherplätze zuweisen (google ALTER SESSION SET SORT_AREA_SIZE). Das kann andere Prozesse in der Datenbank beschädigen, aber Ihre Datenbankadministratoren geben Ihnen nicht viele Optionen.

0

Wirklich versuchen, etwas mit den DBAs zu arbeiten. Ja wirklich. Versuchen, die Vorteile zu kommunizieren und ihre Ängste vor einer verschlechterten Leistung zu mildern.

Haben Sie eine Entwicklungsumgebung/Datenbank, um dieses Zeug zu testen?

Wie aktuell müssen die Daten sein?

Wie wäre es mit einer Kopie der Tabelle, die bereits nach ID und Name mit korrekter Indizierung gruppiert ist? Ein Stapeljob könnte so konfiguriert werden, dass er Ihre neue Tabelle einmal pro Nacht aktualisiert.

Aber wenn das nicht funktioniert, aus ...

Wie über all die ID und Namenspaaren zu einer alternativen Datenbank zu exportieren, wo können Sie Gruppe und Index zu Ihrem Vorteil und lassen Sie die DBAs mit all ihren selbstgefällige Starrheit?

SELECT (
     SELECT name 
     FROM table1 
     WHERE id = did 
       AND rownum = 1 
     ) 
FROM (
     SELECT DISTINCT id AS did 
     FROM table1 
     WHERE id IS NOT NULL 
     ) 

Beide Abfragen werden verwenden Sie den Index auf id:

+0

Ja, ich habe eine Testumgebung, und ich probiere Dinge aus, die Leute vorgeschlagen haben. Auch glaube ich nicht, dass die DBAs selbstgefällig und starr sind. Nun, vielleicht sind sie es, aber es ist legitim, vorsichtig zu sein, bevor Sie jeden Index hinzufügen, den jede App auf einem Tisch haben möchte. Also, bevor ich hart dafür drücke, möchte ich meine Enten in einer Reihe haben. –

+2

Gutes Geschäft. Das Hinzufügen eines zusätzlichen Indexes hat wahrscheinlich nur minimale Auswirkungen auf die Lesevorgänge. Der neue Index ist jedoch ein weiteres Objekt, das aufgrund von Einfügungen/Aktualisierungen/Löschungen auf dem neuesten Stand gehalten werden muss. Ich entschuldige mich für ein bisschen beleidigend. Es ist nicht persönlich. Es ist nur so, dass ich manchmal das Gefühl habe, dass wir uns so sehr auf technische Lösungen konzentrieren, dass wir die offensichtlichen nicht-technischen Lösungen übersehen, wie zum Beispiel unsere Bedürfnisse mit anderen in der IT zu diskutieren. – tom

0

Wenn für ein bestimmtes id die gleiche name immer zurückgegeben wird, können Sie das folgende laufen.

Wenn Sie immer noch die NULL Werte benötigen, führen Sie dies:

SELECT (
     SELECT name 
     FROM table1 
     WHERE id = did 
       AND rownum = 1 
     ) 
FROM (
     SELECT DISTINCT id AS did 
     FROM table1 
     WHERE id IS NOT NULL 
     ) 
UNION ALL 
SELECT NULL, name 
FROM table1 
WHERE id IS NULL 
     AND rownum = 1 

Diese weniger effizient sein wird, da die zweite Abfrage nicht Indizes verwenden, aber es wird auf der ersten NULL stoppen sie trifft: if Es ist nah am Anfang der Tische, dann hast du Glück.

Siehe Eintrag in meinem Blog für Leistungsdetails:

0

Dies kann eine bessere Leistung. Es geht davon aus, dass der Name für eine gegebene ID immer gleich ist.

WITH id_list AS (SELECT DISTINCT id FROM table1) 
SELECT id_list.id, (SELECT name FROM table1 WHERE table1.id = id_list.id AND rownum = 1) 
    FROM id_list;