Newsgroup: it.comp.lang.visual-basic
Titolo: LEFT JOIN

ciao a tutti!
ho un problema con una select.....
In sostanza ho la tabella Makkine legate a Documenti tramite il codice
makkina.
Nel mio report voglio visualizzare sia le makkine per cui trovo documenti ke
quelle che non ne hanno.
Cio' l'ho risolto con una left join e fino a qui nessun problema.
A questo punto aggiungo come filtro di selezione anke la data del
documento,nella tabella documenti. E qui arriva la questione!
Se ho ad esempio un cliente con 4 makkine di cui 3 con documenti nel 1999 e
1 con documenti nel 2000,
la left join non funziona quando appliko il filtro.
Essa avviene se non trova corrispondenza,ovvero se trova una makkina con
"nessun documento".
Ma se io appliko anke il filtro di data dall' 1/1/99 al 31/12/99, vengono
visualizzate solo le 3 makkine con i doc. del '99, ma quella con doc. SOLO
del 2000 no.
In effetti è giusto ke sia così,la data non è vuota come se avessi una
makkina di cui non viene trovato riferimento nella tabella documenti....
Potrei ottenere una cosa del genere?
Esempio:
cod. makkina            data doc.
-------------------------------
000001                    31/12/1999                <----doc. del
99.....filtro ok!
000001                    30/12/1999
000002                    15/4/1999                <----doc. del
99.....filtro ok!
000003                    16/8/1999                <----doc. del
99.....filtro ok!
000004                                                    <----HO DOC. del
2000, ma non del 99, quindi mi fa vedere cmq il cod. makkina
000004                                                             come se
si verificasse la left join.
Ho provato a fare il filtro data ("da quella data a quella data" Or "date
nulle"), ma la situazione non si risolve.
Sono molto scettica sulla possibilità che la cosa si possa fare,pero'......
Grazie a tutti
Beba

 Beba
Ciao Beba,
sarebbe stato meglio tu postassi lo script SQL da esaminare
e che specificassi quale DB interroghi (SQL-Server, Oracle, Access)
e come (VB, QueryAnalizer, VBA) e tutti gli altri dettagli che
possono indirizzare meglio la valutazione degli elementi del
problema.
Ipotizzo tu scriva erroneamente i criteri di LEFT JOIN.
Prova a risolvere tu cambiando sintassi; la LEFT JOIN può, in
taluni casi, essere vista come una INNER JOIN in UNION con la
query che preserva i record della tabella LEFT.
Ovvero, prova a trasformare la LEFT JOIN in:
[Assunzione: lavori su DB SQL-Server via StoredProcedure]
SELECT DISTINCT
       MAK.CodMakkina                As "Codice Macchina",
       CONVERT(Varchar, DOC.DataDoc) As "Data Documento"
  FROM Makkine MAK INNER JOIN Documenti DOC
                   ON MAK.CodMakkina = DOC.CodMakkina
WHERE 
      DATEDIFF(dd, DOC.DataDoc, @DataFrom) >= 0  
  AND DATEDIFF(dd, DOC.DataDoc, @DataTo)   <= 0  
UNION ALL
SELECT DISTINCT
       MAK.CodMakkina                As "Codice Macchina",
       "Nessun documento"            As "Data Documento"
  FROM Makkine MAK INNER JOIN Documenti DOC
                   ON MAK.CodMakkina = DOC.CodMakkina
WHERE 
      DATEDIFF(dd, DOC.DataDoc, @DataFrom) < 0  
  AND DATEDIFF(dd, DOC.DataDoc, @DataTo)   > 0  
N.B. La seconda query estrae dati all'esterno dell'intervallo
     date fornito: anche solo un giorno prima o dopo; se ti
     occorre un differente delta tempo, anni per esempio,
     deve venir modificata.
Se il DB non dovesse essere SQL-Server, modifica la sintassi;
la funzione DATEDIFF è necessaria per quelle situazioni in cui
la data è registrata in formato esteso "YYYY-MM-DD hh:mm:ss.nnn",
quindi data + orario, e la si deve comparare con YYYY-MM-DD.
Es: 
   se sul DB per DataDoc avessi: 2001-10-10 13:26:56.956
   poichè settata tramite GETDATE(),
   se volessi compararla con: 2001-10-10,
   allora DATEDIFF(dd, "2001-10-10 13:26:56.956", "2001-10-10") >= 0
   restituisce TRUE e soddifa la condizione.
   Il primo parametro di DATEDIFF, dd, specifica la differenza in
giorni.
Se, analizzando i risultati ottenuti tramite la nuova query, riscontri
divergenze con la LEFT JOIN, allora è verificata la mia ipotesi iniziale
di errore sui criteri.
Altrimenti posta gli script SQL.
HTH
Ciao 
	Adriano

ciao!
allora.....programmo in vb6 e con qs. progetto ho come db MSDE.
la join che ho fatto è:
SELECT Macchine.CodMacchina, Documenti.DtaPrecPrelievo,
    Documenti.DtaAttualePrelievo
FROM dbo.Macchine LEFT OUTER JOIN
    dbo.Documenti ON
    dbo.Documenti.CodMacchina = dbo.Macchine.CodMacchina
presupponevo il fatto che si dovesse modificare la query, ho provikkiato col
tuo suggerimento ma non ne ricavo molto,anke perchè non uso le s.p.....
che faccio? è necessario usare la datediff? mi serve solo visualizzare il
cod.  makkina....
a qs. punto visto che non mi sembra di essere molto afferrata in
query,magari mi faccio una tabellina temporanea in cui sbatto dentro ciò che
voglio,ma mi viene una rabbia,solo per sta scemata!!!!!
ti ringrazio
Beba
"Arj" <A...@Arj.exe> ha scritto nel messaggio
news:3BC4318A...@Arj.exe...


 
Ciao Beba,
MSDE registra i campi DateTime nel formato:
	YYYY-MM-DD hh:mm:ss.nnn
Legenda:
     anno          4 digit [YYYY], 
     separatore    1 [-],
     mese          2 [MM],
     separatore    1 [-],
     giorno        2 [DD],
     separatore    1 [ ],
     ora           2 [hh],
     separatore    1 [:],
     minuti        2 [mm],
     separatore    1 [:],
     secondi       2 [ss],
     separatore    1 [.],
     millisecondi  3 [nnn]
Tu cerchi record compresi in un intervallo
specificato da due date che vengono indicate
dallo user tramite VB.
Ignoro quale controllo ocx utilizzi per consentire
la selezione dell'intervallo, DTPicker o equivalente,
ma presumibilmente le date che poi utilizzi come 
parametri sono in formato diverso da quello
che è riconosciuto dal motore SQL.
Devi quindi formattarle in YYYY-MM-DD hh:mm:ss.nnn 
affinchè siano valide.
Altrimenti devi usare le funzioni a disposizione 
di T-SQL, il dialetto SQL di MSDE.
Es:
 CONVERT(Datetime, "2001-10-20") 
 restituisce "2001-10-20 00:00:00.000"
 N.B. DEVI passare un formato conosciuto e una data valida
      e compatibile alla CONVERT + Datetime.
      Il meglio è YYYY-MM-DD
Se tu cerchi un record nella tabella Documenti, le cui 
date sono nel formato YYYY-MM-DD hh:mm:ss.nnn, esempio
"2001-09-22 12:30:56.987", e  utilizzi nella clausola 
WHERE un'espressione criterio, sulla data, non conforme,
il risultato è nullo.
Ovvero
       SELECT DtaPrecPrelievo,
              DtaAttualePrelievo
         FROM Documenti 
        WHERE DtaPrecPrelievo = "2001-10-20"
non restituirà record.
E probabilmente neppure
       SELECT DtaPrecPrelievo,
              DtaAttualePrelievo
         FROM Documenti 
        WHERE DtaPrecPrelievo = CONVERT(Datetime, "2001-10-20")
restituirà alcun record, poichè difficilmente documenti vengono 
salvati a mezzanotte esatta, sempre perchè
             CONVERT(Datetime, "2001-10-20") 
restituisce "2001-10-20 00:00:00.000" ovvero la mezzanotte.
Per questi motivi si usano DATEDIFF e le altre funzioni di
interpolazione delle date.
Supponiamo che l'utente del tuo applicativo abbia selezionato
le date per vedere i documenti 
	dal "2001-01-01" 
	al  "2001-01-31"
Tu devi trasformarle in date SQL valide, quindi 
	dal "2001-01-01 00:00:00.000"
        al  "2001-01-31 23:59:59.999"
ovvero dal primo millisecondo della giornata di inizio, fino
all'ultimo millisecondo della giornata di fine.
Per "2001-01-01" va bene CONVERT(Datetime, "2001-01-01") 
poichè restituisce proprio "2001-01-01 00:00:00.000"
Non è analogo per "2001-01-31"; infatti
	CONVERT(Datetime, "2001-01-31")
restituirebbe "2001-01-31 00:00:00.000" escludendo di fatto 
tutti i documenti della giornata.
Allora fissiamo un giorno in più:
	DATEADD(dd, 1, CONVERT(Datetime, "2001-01-31"))
che restituisce "2001-02-01 00:00:00.000" (nota che la 
funzione DATEADD aggiunge proprio un giorno di calendario
per cui si passa dal 31 gennaio al primo febbraio)
E quindi, supponendo DataDal e DataAl i nomi delle
variabili rispettivamente della data di inizio e 
di fine selezionata dall'utente, nell'esempio di cui sopra 
rispettivamente "2001-01-01" e "2001-01-31", la query sarà:
[perdona l'impaginazione ma altrimenti il browser ti taglia le
righe e reimpagina a _modo suo_(leggi osceno)]
SELECT Macchine.CodMacchina, 
       Documenti.DtaPrecPrelievo,
       Documenti.DtaAttualePrelievo
  FROM dbo.Macchine 
       LEFT OUTER JOIN dbo.Documenti 
       ON dbo.Documenti.CodMacchina = dbo.Macchine.CodMacchina
 WHERE 
      (
           Documenti.DtaPrecPrelievo 
                    >= 
           CONVERT(Datetime, DataDal)
       AND
           Documenti.DtaAttualePrelievo 
                    < 
           DATEADD(dd, 1, CONVERT(Datetime, DataAl))
      )
   OR 
      (
          Documenti.DtaPrecPrelievo IS NULL
       AND
          Documenti.DtaAttualePrelievo IS NULL
      )
Le parentesi NON sono opzionali.
Il secondo argomento IS NULL potrebbe essere evitato
se i due campi data NON accettano valori NULL nel
design della tabella.
Poi la query la puoi chiamare come vuoi.
da VB:
	Private Sub GetAvailableDocument()
	Dim DataDal      As String
        Dim DataAl       As String
	Dim bContinue    As Boolean
	Dim StrSQL       As String
	Dim SelectClause As String
	Dim FromClause   As String
	Dim WhereClause  As String
	'Retrieve requests
	DataDal = MioControllo.Text
	DataAl  = MioControllo2.Text
	'Validate user input
	bContinue = ValidateDate (DataDal, DataAl)
	if bContinue Then
	   SelectClause = "SELECT Macchine.CodMacchina, " & _ 
       		          "Documenti.DtaPrecPrelievo, " & _ 
       		          "Documenti.DtaAttualePrelievo" 
           FromClause = "FROM dbo.Macchine" & _ 
                        "LEFT OUTER JOIN dbo.Documenti" & _ 
                        "ON dbo.Documenti.CodMacchina =" & _ 
                        "dbo.Macchine.CodMacchina" 
	   WhereClause = "WHERE " & _  
                         "(Documenti.DtaPrecPrelievo >=" & _ 
	                 "CONVERT(Datetime, " & _ 
                          DataDal & ") AND " & _ 
	                 "Documenti.DtaAttualePrelievo <" & _ 
	                 "DATEADD(dd, 1, CONVERT(Datetime, " & _ 
                         DataAl & "))) OR " & _ 
	                 "(Documenti.DtaPrecPrelievo IS NULL" & _ 
			 " AND " & _ 
	          	 "Documenti.DtaAttualePrelievo IS NULL" & _ 
                         ")"
	   StrSQL = SelectClause & FromClause & WhereClause
	   Call DatabaseInquiry(StrSQL, MioControllo3)
	   [etc. etc.]
         End if
	End sub
HTH
Ciao
	Adriano