LEFT JOIN di diverse condizioni

miagy

Utente Attivo
2 Nov 2014
83
1
8
Ciao ragazzi,
scrivo perché vorrei cercare una soluzione riguardo una questione che mi sta attanagliando e da cui non riesco a uscirne.
Ho due tabelle, la prima chiamata chat, la seconda chiamata chat_master.
Nel dettaglio, la tabella chat è così formata:

id_mexid_chatmittenteora (datetime)tipo
La seconda, chat_master, invece così:

id_chatuserdate_start (datetime)date_end (datetime)

Nello specifico, l'obiettivo è quello di dare i permessi di scrivere solo in determinate circostanze.

PHP:
//vedo se è una chat è attiva oppure no

$check = gdrcd_query("SELECT * FROM chat WHERE id_chat = ".$_SESSION['luogo']."", 'result');
if(gdrcd_query($check, 'num_rows') > 0) {
//c'è una chat attiva (vedi codice sotto)
} else {
    //non c'è una chat attiva
}

Questo è il primo passaggio che faccio, e funziona tutto alla perfezione.
All'interno dell'if, qualora mi restituisse un risultato, inizio a porre le condizioni:

1) Passaggio 1.1: Devo selezionare l'ultimo id di chat.mittente ($_SESSION'login']) all'interno di chat.id_id_chat e, se il nome è diverso da chat_master.user, verifico che chat.tipo=P e chat.ora sia > chat_on.date_start MA chat.ora < chat_on.date_end.

PHP:
$info = gdrcd_query("SELECT * FROM chat
                     LEFT JOIN chat_master ON chat_master.id_chat = chat.id_chat
                     WHERE (SELECT max(chat.id)
                     FROM chat WHERE mittente = '".$_SESSION['login']."' &&
                     chat_master.id_chat = chat.id_chat)
                     && chat.ora > chat_master.date_start && chat.ora < chat_master.date_end && chat.mittente != chat_master.user && chat.tipo='P'", 'result');

Fatto questo, stabilisco anche un ulteroriore condizione, ossia vedere se date_end sia abbia generato una scadenza oppure no (se date_end è settato alle 17:00 e mittente scrive alle 17:01, non può farlo).

PHP:
                $check_ora = gdrcd_query("SELECT date_end FROM chat_master WHERE luogo = ".$_SESSION['luogo']."");

A questo punto genero 3 condizioni:

I: Mittente non ha scritto nulla, ma date_end è ormai scaduto:

PHP:
if ((gdrcd_query($info, 'num_rows') < 1) && ($check_ora['date_end'] < 'NOW()')) {
//non c'è neanche risultato, ma il tempo è scaduto e dunque non si può scrivere
}

II: C'è un risultato e mittente ha scritto tra date_start e date_end

PHP:
else if ((gdrcd_query($info, 'num_rows') > 0) && ($check_ora['date_end'] > 'NOW()')) {
//C'è un risultato tra date_start e date_end
}

III: Non c'è nessun risultato, ma il date_end non è scaduto e per questo si può scrivere

PHP:
else {
//puoi scrivere
}

Il codice posto così funziona, salvo in una cosa.
Se io che sono online sono != da chat_master.user, il primo if mi viene riconosciuto (non c'è neanche risultato, ma il tempo è scaduto e dunque non si può scrivere), ma il secondo e il terzo no.
Quindi se ci sono le condizioni per cui O "C'è un risultato tra date_start e date_end" O "non c'è nessun risultato, il date_end non è scaduto e per questo si può scrivere", come risultato mi dà sempre il primo (non c'è neanche risultato, ma il tempo è scaduto e dunque non si può scrivere).

Sapete come mai e dove sbaglio?

Qui il codice intero:

PHP:
$check = gdrcd_query("SELECT * FROM chat_master WHERE id_chat = ".$_SESSION['luogo']."", 'result');

if(gdrcd_query($check, 'num_rows') > 0) {

//c'è una chat attiva

//Passaggio 1.1: Seleziono l'ultimo id di chat.mittente e, se il nome è diverso da chat_on.user, verifico che chat.tipo=P e chat.ora sia > chat_on.date_start MA chat.ora < chat_on.date_end.

$info = gdrcd_query("SELECT * FROM chat
                     LEFT JOIN chat_master ON chat_master.id_chat = chat.id_chat
                     WHERE (SELECT max(chat.id)
                     FROM chat WHERE chat.mittente = '".$_SESSION['login']."' &&
                     chat_master.id_chat = chat.id_chat)
                     && chat.ora > chat_master.date_start && chat.ora < chat_master.date_end &&
                     chat.mittente != chat_master.user && chat.tipo='P'", 'result');
                
//passaggio 1.1: oltre questo, verifico se NOW() abbia superato l'ora di chat_on.date_end. Se il tempo è scaduto, dunque NOW() è superiore a date_end, blocco qualsiasi azione:

$check_ora = gdrcd_query("SELECT * FROM chat_master WHERE luogo = ".$_SESSION['luogo']."");

//valorizzo

if ((gdrcd_query($info, 'num_rows') < 1) && ($check_ora['date_end'] < 'NOW()')) {
//non c'è neanche risultato, ma il tempo è scaduto e dunque non si può scrivere

} else if ((gdrcd_query($info, 'num_rows') > 0) && ($check_ora['date_end'] > 'NOW()')) {
//C'è un risultato tra date_start e date_end
} else {
//non c'è nessun risultato, il date_end non è scaduto e per questo si può scrivere
}


} else {
//non c'è nessuna chat attiva
}
 

WmbertSea

Moderatore
Membro dello Staff
MOD
28 Nov 2014
432
73
28
Ciao, non ho approfondito ma vedo qualcosa che stona nelle condizioni.
Sei sicuro che questa comparazione sia corretta?
PHP:
$check_ora['date_end'] < 'NOW()'
Forse mi sto perdendo qualcosa ma quel 'NOW()', scritto tra apici, non produce forse quell'esatta stringa testuale?!
Ora, non mi è chiaro se lo hai riportato come pseudo-codice o se lo stai usando proprio scritto in quel modo,
Anche se il valore di sinistra fosse un numero, mi suona strano che si possa comparare direttamente con quella stringa.

La comparazione tra valori numerici e stringhe, anche a seconda della versione di PHP usata, può di certo generare dei risultati inconsistenti.

E' forse questo il problema?


Ancora, non mi è chiaro perché stai impostando 3 diverse condizioni (compreso l'else che esclude le altre 2).
La seconda condizione cosa dovrebbe permetterti di fare?
Se devi stabilire solo i casi in cui si può o non si può scrivere, non sarebbe consono avere solo 2 condizioni? O, meglio, una sola condizione e un else?

Tra l'altro, quel tuo ultimo else (per esclusione delle altre 2 condizioni) prevede anche una seconda ipotesi che non hai indicato, cioè il caso in cui "C'è un risultato ma il tempo è scaduto". Non è possibile che avvenga anche questa situazione?

Forse anche qui mi sto perdendo qualcosa.

Fai sapere magari se ti ho dato qualche input che ti permetta di risolvere, altrimenti prova a chiarire.
 

miagy

Utente Attivo
2 Nov 2014
83
1
8
Sei sicuro che questa comparazione sia corretta?
PHP:
$check_ora['date_end'] < 'NOW()'
Forse mi sto perdendo qualcosa ma quel 'NOW()', scritto tra apici, non produce forse quell'esatta stringa testuale?!
Ora, non mi è chiaro se lo hai riportato come pseudo-codice o se lo stai usando proprio scritto in quel modo,
Anche se il valore di sinistra fosse un numero, mi suona strano che si possa comparare direttamente con quella stringa.

La comparazione tra valori numerici e stringhe, anche a seconda della versione di PHP usata, può di certo generare dei risultati inconsistenti.

E' forse questo il problema?
Ciao, intanto ti ringrazio della risposta. Provo a spiegare meglio il problema, e parto proprio da questo primo punto.
Intendi forse dire che il campo 'date_end' (che nel db è settato come datetime) non posso compararlo con NOW()? O che la condizione è sbagliata perché ho usato i due apici?
Non ho capito bene cosa intendi.

Per quanto riguarda il resto:

1) La prima condizione agisce seguendo, sulla teoria, questa condizione logica (?): se in chat.id_chat non è presente nessun messaggio di chat.mittente (il cui nome deve essere diverso da chat_master.user, che è quello che apre la chat) di chat.tipo=P tra chat_master.date_start e chat_master.date_end, ma la chat è ormai scaduta, chat.mittente non può più scrivere nulla. (Esempio: se una chat è aperta tra le 17:00 e le 18:00, io non ho mai scritto nulla e il primo messaggio lo scrivo alle 18:01... il sistema non mi fa scrivere)

2) La seconda condizione: se in chat.id_chat c'è un messaggio di chat.mittente (il cui nome deve essere diverso da chat_master.user, che è quello che apre la chat) di chat.tipo=P, il cui campo chat.ora è tra chat_master.date_start e chat_master.date_end, chat.mittente non può più scrivere nulla. (Esempio: una chat è aperta tra le 17:00 e le 18:00, io ho scritto alle 17:40. Avendo già scritto qualcosa in quel lasso di tempo... il sistema non mi fa scrivere altri mex)

3) Ultima condizione (nell'else): se in chat.id_chat non è presente nessun messaggio di chat.mittente (il cui nome deve essere diverso da chat_master.user, che è quello che apre la chat) di chat.tipo=P tra chat_master.date_start e chat_master.date_end, ma la chat NON è ancora scaduta, chat.mittente può scrivere. (Esempio: se una chat è aperta tra le 17:00 e le 18:00, io non ho ancora scritto nulla e il primo messaggio lo scrivo alle 17:40... il sistema mi fa scrivere).

L'ultimissimo else:

PHP:
} else {
    //non c'è nessuna chat attiva
}

risponde alla primissima condizione, ossia:

PHP:
$check = gdrcd_query("SELECT * FROM chat_master WHERE id_chat = ".$_SESSION['luogo']."", 'result');

if(gdrcd_query($check, 'num_rows') > 0) {

Adesso è più chiaro?
Sì, il codicè è quello che sto usando :D
 

miagy

Utente Attivo
2 Nov 2014
83
1
8
Ragionando, mi è venuto in dubbio:

Affinché la seconda condizione sia vera, forse estrarre l'ultimo chat.id di chat.tipo = P di chat.mittente (che deve essere diverso da chat_master.user) non ha alcun senso, perché se c'è un risultato in quel lasso di tempo deve essere per forza l'ultimo risultato.
Magari cambiare così?

PHP:
$info = gdrcd_query("SELECT * FROM chat
                     LEFT JOIN chat_master ON chat_master.id_chat = chat.id_chat
                     WHERE (chat.mittente = '".$_SESSION['login']."' && chat.mittente != chat_master.user)
                     && chat.ora > chat_master.date_start && chat.ora < chat_master.date_end &&
                     chat.tipo='P'", 'result');
 

WmbertSea

Moderatore
Membro dello Staff
MOD
28 Nov 2014
432
73
28
O che la condizione è sbagliata perché ho usato i due apici?
Sì. Tu cosa ti aspetti che restituisca l'espressione 'NOW()' in un contesto php?

Mi pare di intuire che tu la stia usando come fosse una query sql, ma l'ambito in quel punto è php, se non ho capito male io. In tal caso non puoi aspettarti che quella funzione (che hai scritto come stringa) restituisca qualcos'altro che non sia esattamente quella striga stessa.

Per ottenere la data/tempo corrente, dovrai usare necessariamente una qualche funzione php, che ti restituisca direttamente un qualche valore o che passi eventualmente attraverso una query sql.

Riguardo le 3 condizioni, ripeto, a mio parere dovrebbero essercene solo due: una che consente di scrivere e l'altra che nega di scrivere.
Ragionando, mi è venuto in dubbio
Sì, in effetti hai già posto le condizioni nella query stessa, sia il controllo dell'utente sia il controllo del datetime... almeno, mi pare di capire così.

A quel punto in php, per stabilire che si possa scrivere, devi solo verificare la presenza di un risultato per tale query. Non pensi?
 

miagy

Utente Attivo
2 Nov 2014
83
1
8
In realtà ti ringrazio perché mi ci hai fatto rifettere, ed effettivamente è stata una cosa veramente scema la mia pensata
Ho dunque modificato il tutto, e funziona al 90%. La cosa che mi manca è proprio il controllo di scadenza.
Inserendo questa sintassi, funziona tutto a meraviglia:

PHP:
 $check = gdrcd_query("SELECT * FROM chat_master WHERE luogo = ".$_SESSION['luogo']."", 'result');
                  if(gdrcd_query($check, 'num_rows') > 0) {
                //attiva e dunque valorizzo
                
                $info = gdrcd_query("SELECT * FROM chat
                     LEFT JOIN chat_master ON chat_master.luogo = chat.stanza
                     WHERE (chat.mittente = '".$_SESSION['login']."' && chat_master.user != '".$_SESSION['login']."')
                     && chat.ora > chat_master.date_start && chat.ora < chat_master.date_end
                     && chat.tipo='P'", 'result');
                    
                if (gdrcd_query($info, 'num_rows') < 1) {

                //Può scrivere
                
                } else {
                //non può scrivere
                }
                
                } else {
                //non c'è nessuna chat attiva
                }

Tuttavia, quando inserisco anche che la condizione della scadenza (se sono le 17:30 e la scadenza era alle 17, non posso scrivere, a prescindere che abbia scritto o meno prima), non me lo riconosce:

PHP:
 $check = gdrcd_query("SELECT * FROM chat_master WHERE luogo = ".$_SESSION['luogo']."", 'result');
                  if(gdrcd_query($check, 'num_rows') > 0) {
                //valorizzo
                
                $info = gdrcd_query("SELECT * FROM chat
                     LEFT JOIN chat_master ON chat_master.luogo = chat.stanza
                     WHERE (chat.mittente = '".$_SESSION['login']."' && chat_master.user != '".$_SESSION['login']."')
                     && ((chat.ora > chat_master.date_start && chat.ora < chat_master.date_end) && (chat_master.date_end < NOW()))
                     && chat.tipo='P'", 'result');
                    
                if (gdrcd_query($info, 'num_rows') < 1) {

                //Può scrivere
                
                } else {
                    
                //non può scrivere
                    
                }
                
                } else {
                //nessuna chat attiva
                }

Sai dirmi come mai?
 

WmbertSea

Moderatore
Membro dello Staff
MOD
28 Nov 2014
432
73
28
In realtà ti ringrazio perché mi ci hai fatto rifettere
Non c'è di che, un confronto di idee è sempre utile.

quando inserisco anche che la condizione della scadenza
Scusami ma "chat.ora" cosa restituisce?
Fammi capire, nella tabella chat non lo hai salvato forse con un qualche valore che corrisponde proprio a NOW()?
Se fosse così allora hai già quella condizione esattamente qui:
Codice:
chat.ora > chat_master.date_start && chat.ora < chat_master.date_end
A questo punto non dovrebbe servire altro.
Puoi chiarire?
 

miagy

Utente Attivo
2 Nov 2014
83
1
8
Non c'è di che, un confronto di idee è sempre utile.


Scusami ma "chat.ora" cosa restituisce?
Fammi capire, nella tabella chat non lo hai salvato forse con un qualche valore che corrisponde proprio a NOW()?
Se fosse così allora hai già quella condizione esattamente qui:
Codice:
chat.ora > chat_master.date_start && chat.ora < chat_master.date_end
A questo punto non dovrebbe servire altro.
Puoi chiarire?
Qualora l'utente (chat.mittente) non abbia scritto qualcosa nel range che va da date_start a date_end, faccio un INSERT e imposto il campo 'ora' con NOW(), e mi restituisce il valore corretto (l'ora e la data di invio).
Tutto questo funziona correttamente e assurge a questa parte:

PHP:
if (gdrcd_query($info, 'num_rows') < 1) {
    //può scrivere
}

Da un punto di vista teorico: La chat è aperta dalle 16 alle 18. Sono le 17. L'utente tra le 16 e le 18 non ha scritto nulla -> può scrivere

Tuttavia, nel select che faccio in $info devo mettere un ulteriore clausola, ossia: qualora l'utente non abbia scritto in questo range (16-18), e adesso sono le 19, l'utente non può scrivere perché la chat è chiusa.

Con il codice sopra, questo ultimo passaggio non mi funge, perché l'if mi viene riconosciuto come else {} giacché io utente, effettivamente, tra le 16 e le 18 non ho scritto nulla, dunque se anche adesso sono le 19 questo passaggio non mi viene riconosciuto.
 

WmbertSea

Moderatore
Membro dello Staff
MOD
28 Nov 2014
432
73
28
Forse inizio a capire, mi sfuggiva qualche passaggio :p

Secondo me puoi risolvere impostando la condizione di "tempo scaduto" con un OR logico (anziché un AND) su quella stessa query, in modo che il risultato sia vero se 'l'utente ha già scritto' oppure se 'il tempo è scaduto' e quindi non sia più consentito scrivere.

Una cosa del genere (non testato):
PHP:
$info = gdrcd_query("SELECT * FROM chat
LEFT JOIN chat_master ON chat_master.luogo = chat.stanza
WHERE (chat.mittente = '".$_SESSION['login']."' && chat_master.user != '".$_SESSION['login']."')
&& ((chat.ora > chat_master.date_start && chat.ora < chat_master.date_end) || (chat_master.date_end > NOW()))
&& chat.tipo='P'", 'result');

if (gdrcd_query($info, 'num_rows') < 1) {
  //Può scrivere
} else {
  //non può scrivere
}

Non ho possibilità di testarlo, vedi comunque se la logica può andare bene ed eventualmente cerca tu di aggiustarlo se non dovesse funzionare.
 

miagy

Utente Attivo
2 Nov 2014
83
1
8
Non ho possibilità di testarlo, vedi comunque se la logica può andare bene ed eventualmente cerca tu di aggiustarlo se non dovesse funzionare.
Hm, non mi funge.
Mettendo quella clausola, in realtà mi vien meno anche la clausola precedente.
Non so veramente dove sbattere la testa!
 

WmbertSea

Moderatore
Membro dello Staff
MOD
28 Nov 2014
432
73
28
Il fatto che con quell'OR non funzioni nemmeno la prima espressione, mi fa venire il dubbio che la funzione NOW() non sia supportata dal tuo sql e quindi si generi un errore. Hai possibilità di verificare in qualche modo?

In alternativa prova ad usare GETDATE() al posto di NOW() e vedi se cambia qualcosa.
 
Discussioni simili
Autore Titolo Forum Risposte Data
M Estrarre valori MAX da un db con una left join MySQL 8
F [MySQL] Problema con LEFT JOIN MySQL 6
P [MySQL] Inner Join o Left Join MySQL 14
R [PHP] Estrapolare dati da una query left join PHP 0
Marco_88 Eliminare una colonna da una LEFT JOIN MySQL 4
D LEFT JOIN... non ci capisco nulla PHP 2
H Mysql - left join PHP 9
F slide left e right jQuery 0
asevenx struttura DIV realizzata con float: left che si spezza HTML e CSS 3
Monital I div non si accostano con float:left HTML e CSS 1
asevenx div che non si estende oltre il flot:left HTML e CSS 11
B Sql con left Classic ASP 1
F Problema con len e con left Classic ASP 10
wer16 errore in ie con float left HTML e CSS 2
G Css:sempre clear both o è necessario solo left o right? HTML e CSS 0
A style.left Javascript 0
A margin-left: 0 auto; HTML e CSS 3
G altezza di un div che contiene 2 div float:left HTML e CSS 6
B Calcolare Top e Left in base a Risoluzione Classic ASP 11
B Top e Left Javascript 20
L Soluzione con INNER JOIN Database 0
K Problema Inner join PHP 1
L Problema con inner join PHP 11
K [php] Problema con inner join PHP 4
R Join articolato su 3 tabelle MySQL 5
M Join 3 tabelle PHP 0
L select join e sottrazione punti PHP 13
M Problema su query JOIN in tre tabelle PHP 0
MarcoGrazia Dati nulli su join tra più tabelle MySQL 1
M Ordinare una query join PHP 2
P Query Mysql con Join PHP 2
S [PHP] Inner join su 4 tabelle PHP 6
M [PHP] Aiuto su inner join PHP 10
simgia [PHP] Ciclare una query JOIN PHP 2
simgia [MySQL] INNER JOIN problema MySQL 0
C Php/Mysql query JOIN tra tabelle PHP 4
C Php/Mysql query JOIN tra due tabelle PHP 18
R [MySQL] SQL UPDATE INNER JOIN MySQL 5
G [MS Access] JOIN di due tabelle più GROUP BY MS Access 1
G [MySQL] Join o select MySQL 1
R [MySQL] Join, Count e Order (ASC & DESC)... MySQL 6
B Outer join che non funge Database 2
jdj78 inner join Classic ASP 18
V [Guida]: ho dubbi sulle Join MySQL 13
P Query con Somma di un Campo , aggregazione e join Database 3
V Quando mettere il JOIN e quando no? MySQL 1
L cinque tabelle e join PHP 2
P Join tabelle MySQL 4
Marco_88 Select distinct e join MySQL 2
M Query Join per 2 colonne MySQL 1

Discussioni simili