2016-04-10 21 views
1

Ich möchte die folgende Abfrage ändern, so dass anstelle der Spalte ORDER.S_ID den Wert der entsprechenden NAME-Spalte aus der Tabelle (namens STORES) S_ID abgerufen bezieht sich auf.Oracle SQL ersetzen eine Return-Spalte mit einem Nullwert

In einigen Fällen ist S_ID jedoch null, in diesem Fall gibt es keine entsprechende Namensspalte. In diesem Fall gibt es noch Aufzeichnungen aus der Ordnung und ORDER Tabellen, die ich COUNT will (*) - ed und somit von der Abfrage angezeigt, so dass die zweite Säule der Ergebnismenge

SELECT 
COUNT(*), ORDER.S_ID 
FROM 
ORDER, ORDERLIST 
WHERE 
ORDERLIST.O_ID = ORDER.ID AND 
ORDER.DATE = '13-APR. -09 19.42.05,259000000' 
GROUP BY S_ID; 

Beispieldaten null ist:

ORDER Tisch

ID DATE       S_ID 
----------------------------------------    
1 11-APR. -09 19.41.39,187000000 null 
2 12-APR. -09 19.42.05,259000000 null 
3 13-APR. -09 19.42.41,688000000 null 
11 16-APR. -09 22.06.11,169000000 3 

ORDER Tisch

O_ID B_ID PRICE 
--------------------- 
3  6  7999 
2  2  2000 
2  6  7999 
1  5  5000 
1  1  1000 
11  4  4000 
11  6  7999 

STORES t Lage

ID NAME 
---------- 
1 Store1 
2 Store2 
3 Store3 

Was ich wieder sehen möchte, wenn eine Benutzer-Abfragen für ein Datum, wo der S_ID Wert nicht null ist: (dieser spezielle Fall ist, wenn das Datum 16-April abgefragt. -09 22.06.11,169000000)

COUNT(*) STORENAME 
2  Store3 

Was ich zurückgegeben werden soll, wenn es null. (für das Datum 13-April Abfrage -09 19.42.41,688000000)

COUNT(*) STORENAME 
1  null 

Antwort

1

Wie Gordon sagte, benötigen Sie einen Outer Join, und es ist viel besser, die richtige Joinsyntax zu verwenden - insbesondere bei Outer Joins, aber immer und überall, egal, was Ihr Tutor verwendet.

Da Sie von der Bestellung beginnen und kann haben einen passenden Speicher, Sie müssen die auf die Tabelle stores verbinden die äußeren sein beitreten:

SELECT o.s_id, s.name, count(*) 
FROM "ORDER" o 
JOIN orderlist ol ON ol.o_id = o.id 
LEFT JOIN stores s ON s.id = o.s_id 
--WHERE o."DATE" = TO_TIMESTAMP('13-APR. -09 19.42.05,259000000', 'DD-MON". "-RR HH24.MI.SS,FF9') 
GROUP BY o.s_id, s.name; 

     S_ID NAME  COUNT(*) 
---------- ------ ---------- 
          5 
     3 Store3   2 

Seit ‚bestellen‘ und ‚date‘ sind reservierte Wörter, für die ich zitierte Bezeichner verwenden musste, aber sie dürfen nicht die richtigen Namen sein. Verwenden Sie keine Bezeichner in Anführungszeichen, wenn Sie diese möglicherweise vermeiden können. Ich habe Tabellenalias verwendet, um das etwas weniger schmerzhaft zu machen. Das 'Datum' ist auch ein Zeitstempel und nicht ein Datum, da Sie Sekundenbruchteile haben, was den Namen noch verwirrender macht.

Ich habe die Datums-/Zeitstempeleinschränkung auskommentiert, weil sie mit keinem Ihrer Beispieldaten übereinstimmte, und wenn sie auf den 12. April geändert wurde, fand sie immer noch nur eine, was als Demo nicht sehr hilfreich war. Ihr NLS_TIMESTAMP_FORMAT ist ... ungewöhnlich, aber das ist ein separates Problem.Zum Vergleich ist es einfacher, einen Zeitstempel zu verwenden wörtlichen:

WHERE o."DATE" = TIMESTAMP '2009-04-12 19:42:05.259000000' 

Beachten Sie, dass Doppelpunkte und eine Periode als Dezimalbruch Separator für den Sekundenwert hat, im Gegensatz zu Ihrem NLS_TIMESTAMP_FORMAT.


Wenn Ihr Lehrer wirklich auf der alten beharrt, Oracle-spezifische Join-Syntax Sie dann können ordnen es als:

SELECT o.s_id, s.name, count(*) 
FROM "ORDER" o, orderlist ol, stores s 
WHERE ol.o_id = o.id 
AND s.id (+) = o.s_id 
--AND o."DATE" = TIMESTAMP '2009-04-12 19:42:05.259000000' 
GROUP BY o.s_id, s.name; 

... aber es ist viel schwieriger, herauszufinden, was passiert, und viel leichter einen Fehler in den Join-Bedingungen zu machen (oder einen komplett auszulassen). Bitte verwenden Sie die richtige ANSI-Joinsyntax ...

+0

Vielen Dank, Ihre Lösung hat einwandfrei funktioniert, genau das, was ich brauchte! Wenn ich mich richtig erinnere, zeigt der SQL-Entwickler Zeitstempel in einem Format an, das aus dem Betriebssystem des Benutzers und seiner Lokalisierung extrahiert wird. Meine werden angezeigt wie die, die ich eingefügt habe * shrug * –

+1

@aurellb Wenn Sie das Datumsformat in SQL Developer ändern wollen, dann gehen Sie zu 'Extras> Einstellungen ...' erweitern Sie dann die 'Database> NLS' Optionen und ändern Sie das Datum oder Timestamp-Format dort (zu etwas wie "YYYY-MM-DD HH24: MI: SS" für ein Datum oder "YYYY-MM-DD HH24: MI: SSXFF" für Zeitstempel). – MT0

+0

Sie können dies in den Einstellungen überschreiben (es gibt einen NLS-Abschnitt) oder mit 'alter session'. Aus reiner Neugier, welcher Ort produziert das? Ich würde Französisch erraten, außer es wäre "Avr." Anstatt "Apr.", denke ich. Die Leerzeichen in der Monatsabkürzung können auch durch Ändern des Standardformats unterdrückt werden. –

0

Verwenden left join. In der Tat immer explizite join Syntax verwenden. Nie Kommas in der from Klausel:

SELECT s.id, s.name, count(ol.o_id) 
FROM stores s left join 
    order o 
    on s.id = o.s_id left join 
    orderlist ol 
    on ol.o_id = o.id and 
     o.DATE = '13-APR. -09 19.42.05,259000000' 
GROUP BY s.id, s.name; 

Die Verwendung von Kommas in der from Klausel ist seit etwa zwei Jahrzehnten out-of-date gewesen. Sie sollten auch etwas über äußere Verbindungen erfahren.

+0

Sie haben vergessen, die Klammer der ersten Zahl zu schließen(): o Vielen Dank für Ihren Vorschlag, ich werde es sofort ausprobieren! Leider lehren sie uns diese veraltete Syntax (ich bin immer noch Student) –

+0

Diese Abfrage gibt einen Fehler beim Ausführen in SQL Developer mit der Forderung nach ungültiger Anzahl von Argumenten für die erste count() -Klausel. –