2017-05-12 5 views
1

Ich arbeite, um vorzubereiten, was eine relativ einfache Abfrage über ODBC auf einem iSeries-Server sein sollte. Ich möchte, dass ein Segment der Daten zurückgegeben wird, unabhängig davon, welche Verknüpfung für einen von uns erstellten Bericht besteht. Hier ist die Abfrage:DB2 Links Join Abfrage Schwierigkeiten

Select SCDATA.SCCLNT.CCLNT, 
    SCDATA.SCCLNT.CNAME, 
    SCDATA.SCCLNT.CLTGRP As Group, 
    CONCAT(TRIM(SCDATA.SCCLNT.CADD1), SCDATA.SCCLNT.CADD2) As Address1, 
    CONCAT(TRIM(SCDATA.SCCLNT.CCITY), CONCAT(', ', 
     CONCAT(TRIM(SCDATA.SCCLNT.CSTATE), CONCAT(' ', 
     TRIM(SCDATA.SCCLNT.CZIP))))) 
     As Address2, 
    SCDATA.SCACCT.GCLNT, 
    SCDATA.SCACCT.GPLACE, 
    SCDATA.SCACCT.GPLDAT, 
    SCDATA.SCACCT.GACCT# As GACCTnum, 
    CONCAT(TRIM(SCDATA.SCACCT.GLAST), CONCAT(', ', 
    TRIM(SCDATA.SCACCT.GFIRST))) As 
    Debtor, 
    CONCAT((Select 
    VARCHAR_FORMAT(Min(TIMESTAMP_FORMAT(Cast(SCDATA.SCACCT.GPLDAT 
    As Char(10)), 'YYYYMMDD')), 'MM/DD/YYYY') From SCDATA.SCACCT 
    Where SCDATA.SCACCT.GPLDAT Between 20170401 And 20170501), CONCAT(' 
    - ', (Select 
    VARCHAR_FORMAT(Max(TIMESTAMP_FORMAT(Cast(SCDATA.SCACCT.GPLDAT As 
    Char(10)), 'YYYYMMDD')), 'MM/DD/YYYY') From SCDATA.SCACCT 
    Where SCDATA.SCACCT.GPLDAT Between 20170401 And 20170501))) As 
    dateRange 
From SCDATA.SCCLNT 
    Left Outer Join SCDATA.SCACCT On 
    CDATA.SCACCT.GCLNT = SCDATA.SCCLNT.CCLNT 
Where SCDATA.SCACCT.GPLDAT Between 20170401 And 20170501 And 
    SCDATA.SCCLNT.CLTGRP Like '######' 

Diese Abfrage funktioniert gut, wenn die SCACCT Tabellenwerte zurückgibt, aber ich brauche mindestens eine einzelne Zeile von SCCLNT auf Kundendaten in dem Bericht zu füllen. Die von uns verwendete Berichtssoftware (DBExtra.net) unterstützt nicht mehrere Abfragen pro Bericht, daher muss alles in einer einzelnen Abfrage gebündelt werden.

Leider ist SQL jenseits von Basisabfragen keine meiner Stärken, daher wird jede Hilfe geschätzt. Vielen Dank.

+0

Sie haben Bedingungen in Ihrer WHERE-Klausel, die sich auf Spalten in SCACCT beziehen (die Tabelle, mit der Sie sich äußerlich verbinden), was bedeutet, dass keine Nullzeilen aus der äußeren Verknüpfung zurückgegeben werden. Enthalten Sie entweder diese Bedingungen in der Join-Klausel, oder schließen Sie null in allen Bedingungen ein: (gpldat zwischen x und y oder gpldata ist null) und (cltgrp wie '######' oder cltgrp ist null) –

+0

Randnotiz - Bitte verwenden Sie eine exklusive Obergrenze ('<') für Datum/Zeit/Zeitstempelabfragen, [oder riskieren Sie unbeabsichtigte Daten] (http://sqlblog.com/blogs/aaron_bertrand/archive/2011/10/19/what-do -zwischen-und-der-Teufel-haben-in-common.aspx). –

Antwort

1

Es besteht ein Widerspruch zwischen Left Outer Join SCDATA.SCACCT und Where SCDATA.SCACCT.GPLDAT Between 20170401 And 20170501. Was können Sie tun, ist bewegen diese WHERE Klausel in die ON-Klausel der äußeren Verknüpfung, so dass die Datumskriterien gilt vor SCACCT-SCCLNT verbunden ist:

From SCDATA.SCCLNT 
    Left Outer Join SCDATA.SCACCT On 
    CDATA.SCACCT.GCLNT = SCDATA.SCCLNT.CCLNT And 
    SCDATA.SCACCT.GPLDAT Between 20170401 And 20170501 
Where SCDATA.SCCLNT.CLTGRP Like '######' 

Siehe Filter Table Before Applying Left Join für eine Erklärung.

+0

Das hat perfekt funktioniert, danke. Jetzt muss ich nur herausfinden, wie ich meinen Bericht dazu bringen kann, die Nullwerte im Detailsegment zu eliminieren :) Ich schätze die Hilfe. – Geoff

+0

@Geoff Sie können 'GROUP BY' hinzufügen, um zu vereinfachen, wie Sie Ihre berechnete Spalte' dateRange' erstellen. Wenn Sie NULL-Werte ersetzen möchten, verwenden Sie 'VALUE (Ausdruck, Ausdruck ...)', die das erste Nicht-Null-Argument zurückgibt – Stavr00

0

Wahrscheinlich nicht, was Sie wollten, genau, aber falls jemand findet sonst diese Frage aus dem Grund, die ich im Sinn hatte:

Hier ist, wie mindestens eine Zeile zu erzeugen (nur den relevanten Teil zu wiederholen):

From SYSIBM.DUAL 
    Left Outer Join (
    Select * 
    From SCDATA.SCCLNT 
     Left Outer Join SCDATA.SCACCT On 
     CDATA.SCACCT.GCLNT = SCDATA.SCCLNT.CCLNT 
    Where SCDATA.SCACCT.GPLDAT Between 20170401 And 20170501 And 
    SCDATA.SCCLNT.CLTGRP Like '######' 
) t On 1 = 1 

Beachten Sie, wie ich Ihre ursprüngliche Abfrage in einer abgeleiteten Tabelle mit der Bezeichnung t umgebrochen habe. Das bedeutet:

  • Sie werden mehrdeutige Spaltennamen handhaben müssen
  • Sie zu dereferenzieren Ihre Spalten von t haben werden, nicht mehr von SCCLNT oder SCACCT

SYSIBM.DUAL garantiert immer enthalten genau eine Reihe.