aiuto query mysql

Forum dedicato alla programmazione.

Moderatore: Staff

Regole del forum
1) Citare in modo preciso il linguaggio di programmazione usato.
2) Se possibile portare un esempio del risultato atteso.
3) Leggere attentamente le risposte ricevute.
4) Scrivere i messaggi con il colore di default, evitare altri colori.
5) Scrivere in Italiano o in Inglese, se possibile grammaticalmente corretto, evitate stili di scrittura poco chiari, quindi nessuna abbreviazione tipo telegramma o scrittura stile SMS o CHAT.
6) Appena registrati è consigliato presentarsi nel forum dedicato.

La non osservanza delle regole porta a provvedimenti di vari tipo da parte dello staff, in particolare la non osservanza della regola 5 porta alla cancellazione del post e alla segnalazione dell'utente. In caso di recidività l'utente rischia il ban temporaneo.
Avatar utente
darkstaring
Linux 3.x
Linux 3.x
Messaggi: 639
Iscritto il: mer 13 ott 2010, 13:55
Nome Cognome: Francesco Achenza
Desktop: KDE
Distribuzione: Arch Linux
Contatta:

aiuto query mysql

Messaggio da darkstaring »

Buonasera, vorrei fare una query ma non sò da dove iniziare...

Ho una tabella Dipendenti ed una altra contratti, dove contratti ha all'interno id_dipendente come chiave esterna.....
Ora mi chiedo come posso sapere i dipendenti che non sono presenti nella tabella contatti senza l'uso di php ma con solo mysql?

spero di esser stato chiaro......
non ho mai fatto niente di simile :D

Grazie
Francesco

Avatar utente
conraid
Staff
Staff
Messaggi: 13460
Iscritto il: gio 14 lug 2005, 0:00
Nome Cognome: Corrado Franco
Slackware: current64
Desktop: kde
Località: Livorno
Contatta:

Re: aiuto query mysql

Messaggio da conraid »

Oddio, mi son reso conto che dopo tanto tempo senza lavorare con sql mi son dimenticato le basi :/

Comunque dovrebbe essere questo
https://dev.mysql.com/doc/refman/5.7/en ... eries.html

Avatar utente
darkstaring
Linux 3.x
Linux 3.x
Messaggi: 639
Iscritto il: mer 13 ott 2010, 13:55
Nome Cognome: Francesco Achenza
Desktop: KDE
Distribuzione: Arch Linux
Contatta:

Re: aiuto query mysql

Messaggio da darkstaring »

Grazie della risposta conraid .. ma non riesco..sapresti aiutarmi?
Ho messo giu questo
SELECT * FROM scadenza_contratti WHERE id_dip NOT EXISTS IN (SELECT id FROM dipendenti);
ma non funziona...
Sai aiutarmi?

Avatar utente
conraid
Staff
Staff
Messaggi: 13460
Iscritto il: gio 14 lug 2005, 0:00
Nome Cognome: Corrado Franco
Slackware: current64
Desktop: kde
Località: Livorno
Contatta:

Re: aiuto query mysql

Messaggio da conraid »

Così su due piedi no, ho veramente rimosso tutto dal cervello, però la sottoquery non è come hai fatto tu, più una cosa simile a questa (sicuramente sbagliata eh :) tanto per farmi capire):

SELECT * FROM scadenza_contratti WHERE NOT EXISTS (SELECT * FROM dipendenti scadenza_contratti.id_dip = dipendenti.id)

al limite prova a mettere un esempio, popolo un database e provo (che mi serve anche per riprendere un po')

Avatar utente
darkstaring
Linux 3.x
Linux 3.x
Messaggi: 639
Iscritto il: mer 13 ott 2010, 13:55
Nome Cognome: Francesco Achenza
Desktop: KDE
Distribuzione: Arch Linux
Contatta:

Re: aiuto query mysql

Messaggio da darkstaring »

Ti mostro la mia struttura

Codice: Seleziona tutto

CREATE TABLE IF NOT EXISTS dipendenti
				    (
					id INTEGER primary key AUTO_INCREMENT,
					nome varchar(50) NOT NULL,
					cognome varchar(50) NOT NULL,
					data_nascita date,
					cod_fiscale varchar(16),
					telefono varchar(30) DEFAULT NULL,
					telefono_urgenza VARCHAR(30) DEFAULT NULL,
					email varchar(30) DEFAULT NULL,
					via varchar(30) DEFAULT NULL,
					citta varchar(30) DEFAULT NULL,
					cap varchar(5) DEFAULT NULL,
					descrizione TINYTEXT DEFAULT NULL,
					attivo BOOL not null,
					username VARCHAR(50) NOT NULL,
					passwd VARCHAR(50) NOT NULL,
					img_profile VARCHAR(30) DEFAULT NULL,
					UNIQUE (username)
				    ) ENGINE=MyISAM;
				    
				    
CREATE TABLE IF NOT EXISTS scadenza_contratti
				    (
					id INTEGER primary key AUTO_INCREMENT,
					id_dip INT NOT NULL,
					descrizione TINYTEXT DEFAULT NULL,
					data_inizio_contratto DATE NOT NULL,
					data_fine_contratto DATE NOT NULL,
					FOREIGN KEY (id_dip) REFERENCES dipendenti(id) ON DELETE CASCADE ON UPDATE CASCADE
				    ) ENGINE=MyISAM;

agharta
Linux 0.x
Linux 0.x
Messaggi: 81
Iscritto il: lun 17 dic 2007, 13:58
Località: Bassano del grappa

Re: aiuto query mysql

Messaggio da agharta »

select dip.* from dipendenti dip
left join scadenza_contratti sc on (dip.id = sc.id_dip)
where sc.id is null


Così è molto più veloce di un not exists/in(select...)

Avatar utente
darkstaring
Linux 3.x
Linux 3.x
Messaggi: 639
Iscritto il: mer 13 ott 2010, 13:55
Nome Cognome: Francesco Achenza
Desktop: KDE
Distribuzione: Arch Linux
Contatta:

Re: aiuto query mysql

Messaggio da darkstaring »

agharta ha scritto:select dip.* from dipendenti dip
left join scadenza_contratti sc on (dip.id = sc.id_dip)
where sc.id is null


Così è molto più veloce di un not exists/in(select...)
Bravo agharta complimenti :D , ho appena visto e sto cercando di capire...
vorrei anche modificare in modo da avere tutti i dipendenti sia con contratto scaduto che senza...
Per ora facevo una query che mi restituisse i dipendenti e un ciclo tra di essi per vedere se con contratto regolare..
provo a modificare quel che mi hai scritto....
Grazie 1000 =D>

agharta
Linux 0.x
Linux 0.x
Messaggi: 81
Iscritto il: lun 17 dic 2007, 13:58
Località: Bassano del grappa

Re: aiuto query mysql

Messaggio da agharta »

Codice: Seleziona tutto

select dip.* from dipendenti dip
left join scadenza_contratti sc on (
dip.id = sc.id_dip 
)
where sc.id is null or sc.data_fine_contratto < CURRENT_DATE /*o la data che ti interessa*/
Provo a spiegarmi.
La tabella principale è quella dei dipendenti.
con la left join ci attacchi la scadenza_contratti matchando x id della tabella dei dipendenti.
In questo modo hai tutti i dipendenti con collegati i record di scandenza_contratti.
where sc.id_dip is null mi da i dipendenti che NON hanno dati in scadenza_contratti
or sc.data_fine_contratto < CURRENT_DATE mi da anche chi ha la data_fine_contratto inferiore ad oggi (scaduti)
select dip.* ....beh, ti da fuori la solo tabella dipendenti. se ti serve anche la colonna sc.data_fine_contratto basta che aggiungi un ", sc.data_fine_contratto"


Allo stesso modo puoi escludere quelli che hanno data_inizio_contratto > della data che ti interessa

Codice: Seleziona tutto

select dip.* from dipendenti dip
left join scadenza_contratti sc on (
dip.id = sc.id_dip 
and sc.data_inizio_contratto <= CURRENT_DATE /*o la data che ti interessa*/
)
where sc.id is null or sc.data_fine_contratto < CURRENT_DATE /*o la data che ti interessa*/
La condizione or non è molto performante in sql, ti conviene inserire un indice nel campo data_fine_contratto e data_inizio_contratto.

Non conoscendo la versione di mysql utilizzata non posso ottimizzarla ulteriormente, spero ti basti.

Ciao

Avatar utente
darkstaring
Linux 3.x
Linux 3.x
Messaggi: 639
Iscritto il: mer 13 ott 2010, 13:55
Nome Cognome: Francesco Achenza
Desktop: KDE
Distribuzione: Arch Linux
Contatta:

Re: aiuto query mysql

Messaggio da darkstaring »

Grazie ..funziona :D
Dovrei fare delle lezioni sulle join...Chissa quanto processore potrei rispiarmiare con un uso corrertto di mysql....

Grazie

agharta
Linux 0.x
Linux 0.x
Messaggi: 81
Iscritto il: lun 17 dic 2007, 13:58
Località: Bassano del grappa

Re: aiuto query mysql

Messaggio da agharta »

Di nulla!
darkstaring ha scritto:---Chissa quanto processore potrei rispiarmiare con un uso corrertto di mysql....
Tantissimo! Personalmente, lavorando con i maggiori db vendor posso assicurarti un fattore velocità almeno 10x (ho casi di 2000x !!!!).

Ricordati di creare gli indici, in linea di massima le query vanno più veloci se utilizzano gli indici (e il motore db li usa in modo corretto....)

Ciaooo

Avatar utente
darkstaring
Linux 3.x
Linux 3.x
Messaggi: 639
Iscritto il: mer 13 ott 2010, 13:55
Nome Cognome: Francesco Achenza
Desktop: KDE
Distribuzione: Arch Linux
Contatta:

Re: aiuto query mysql

Messaggio da darkstaring »

Salve a tutti...
vorrei prelevare dei record da diverse tabelle..

immagino una query simile a questa:

Codice: Seleziona tutto

select ind.*, orari.* 
from cat_zone, zone,  dipendenti 
left join indisponibilita as ind on ind.id_dipendente=dipendenti.id
LEFT JOIN orari on  orari.id_dipendente=dipendenti.id
WHERE orari.id_zona=zone.id AND zone.id_cat_zone=cat_zone.id AND date(orari.tempo_inizio) >= '2017-06-05' AND date(orari.tempo_fine) <= '2017-06-12' AND dipendenti.id=orari.id_dipendente ORDER BY orari.tempo_inizio, ind.tempo_inizio, dipendenti.cognome ;
Mi aspettavo NULL tra i record di indisponibilitama quando era presente un orario e viceversa...
invece tutti i record sono pieni:

Codice: Seleziona tutto

+------+-------------+---------------+---------------------+---------------------+------+---------+---------------+---------------------+---------------------+------------+
| id   | id_tipo_ind | id_dipendente | tempo_inizio        | tempo_fine          | id   | id_zona | id_dipendente | tempo_inizio        | tempo_fine          | definitivo |
+------+-------------+---------------+---------------------+---------------------+------+---------+---------------+---------------------+---------------------+------------+
|    2 |           1 |             3 | 2017-03-29 00:00:00 | 2017-03-31 23:59:00 |  108 |       1 |             3 | 2017-06-05 00:00:00 | 2017-06-05 11:00:00 |          0 |
|    3 |           1 |             3 | 2017-06-07 00:00:00 | 2017-06-09 23:59:00 |  108 |       1 |             3 | 2017-06-05 00:00:00 | 2017-06-05 11:00:00 |          0 |
|    1 |           1 |             2 | 2017-03-24 00:00:00 | 2017-03-25 23:59:00 |  109 |       2 |             2 | 2017-06-06 00:00:00 | 2017-06-06 10:00:00 |          0 |
|    1 |           1 |             2 | 2017-03-24 00:00:00 | 2017-03-25 23:59:00 |  110 |       2 |             2 | 2017-06-08 00:00:00 | 2017-06-08 10:00:00 |          0 |
|    1 |           1 |             2 | 2017-03-24 00:00:00 | 2017-03-25 23:59:00 |  111 |       2 |             2 | 2017-06-09 00:00:00 | 2017-06-09 10:00:00 |          0 |
|    1 |           1 |             2 | 2017-03-24 00:00:00 | 2017-03-25 23:59:00 |  112 |       2 |             2 | 2017-06-11 00:00:00 | 2017-06-11 10:00:00 |          0 |
+------+-------------+---------------+---------------------+---------------------+------+---------+---------------+---------------------+---------------------+------------+
Se non sono stato chiaro chiedete...Grazie

---
Allego il db

---
Ultima modifica di darkstaring il sab 17 giu 2017, 12:55, modificato 1 volta in totale.

agharta
Linux 0.x
Linux 0.x
Messaggi: 81
Iscritto il: lun 17 dic 2007, 13:58
Località: Bassano del grappa

Re: aiuto query mysql

Messaggio da agharta »

Ciao,
Io non vedo il problema: nel tuo file sql il campo indisponibilita.id_dipendente è not null e sempre valorizzato.
La left join è basata sull'id del dipendente, quindi sempre valida. Non viene mai filtrata dalla clausola where.
Ti consiglio di:
1. USARE LE PARENTESI NEI JOIN DOPO 'ON'
2. NON fare un prodotto cartesiano tra cat_zone, zone e dipendenti in quanto il risultato aumenta esponenzialmente all'aumentare dei record. Usa una inner join piuttosto, così sostituisci un po' di clausole where e non massacri cpu, disco e ram.
3. Crea degli indici. Non ne ho trovati nel tuo script. A runtime avrai problemi di presentazione se non li usi. Magari mettili sulle date e sul cognome, visto che è nell'order by.
4. Usa gli alias per tutte le tabelle.

Ciao

Avatar utente
darkstaring
Linux 3.x
Linux 3.x
Messaggi: 639
Iscritto il: mer 13 ott 2010, 13:55
Nome Cognome: Francesco Achenza
Desktop: KDE
Distribuzione: Arch Linux
Contatta:

Re: aiuto query mysql

Messaggio da darkstaring »

agharta ha scritto: 1. USARE LE PARENTESI NEI JOIN DOPO 'ON'
2. NON fare un prodotto cartesiano tra cat_zone, zone e dipendenti in quanto il risultato aumenta esponenzialmente all'aumentare dei record.
Usa una inner join piuttosto, così sostituisci un po' di clausole where e non massacri cpu, disco e ram.
3. Crea degli indici. Non ne ho trovati nel tuo script. A runtime avrai problemi di presentazione se non li usi. Magari mettili sulle date e sul cognome, visto che è nell'order by.
4. Usa gli alias per tutte le tabelle.
Grazie Agharta, ma non riesco...
1. USARE LE PARENTESI NEI JOIN DOPO 'ON' => OK
2. NON fare un prodotto cartesiano tra cat_zone, zone e dipendenti in quanto il risultato aumenta esponenzialmente all'aumentare dei record.
Usa una inner join piuttosto, così sostituisci un po' di clausole where e non massacri cpu, disco e ram.

Quà ho difficolta non ho capito...

3. Crea degli indici. Non ne ho trovati nel tuo script. A runtime avrai problemi di presentazione se non li usi. Magari mettili sulle date e sul cognome, visto che è nell'order by.

Quà ho difficolta non ho capito...


4. Usa gli alias per tutte le tabelle. => Credo ok se intendi "as"

------------------------------
In pratica vorrei avere come risultato una tabella con i record da orari e da indisponibilita... e se è un orario, devo avere anche tutte le info su zone e cat_zone...
Altrimenti tutto a null.. in modo da capire in php se è un orario oppure una indisponibilita
Spero di essere stato chiaro
------------------------------
Grazie

agharta
Linux 0.x
Linux 0.x
Messaggi: 81
Iscritto il: lun 17 dic 2007, 13:58
Località: Bassano del grappa

Re: aiuto query mysql

Messaggio da agharta »

Ciao,
Perdonami ma ero in ferie.

2. Allora, quando fai un "from tabella1, tabella2" il motore sql moltiplica internamente le righe della tabella1 x la tabella 2 (tralascio volutamente le condizioni di where in quanto alcuni db ottimizzano in parte la moltiplicazione).
Questo significa che se tabella1 ha 10 record e tabella2 ne ha 100, il risultato in memoria prima del where sarà 1000 record. Viene da se che se le tabelle sono 3, come nel suo caso, ti troverai migliaia (milioni?) di record in memoria o in file temporanei del db per nulla, con notevole spreco di tempo/risorse.
Nel tuo caso la tabella cardine è la tabella dei dipendenti. Ti consiglio di partire da quella e fare degli inner/left join includendo le clausole where. Qui delle linee guida sui join http://www.w3resource.com/sql/joins/sql-joins.php

3. Il motore database tende ad usare degli indici, se presenti. Gli indici (almeno quelli standard) vengono aggiornati al momento dell'insert/update/delete di un record nella tabella. Se non ci sono gli indici il motore db dovrà scansionare riga per riga e campo per campo, rallentando di molto. Guarda qui http://www.w3resource.com/sql/creating- ... -index.php

Per il risultato, non trovo più il tuo script sql. Se lo ripubblichi (anche solo in parte) o me lo mandi in pv, vedo di prepararti una query ottimizzata.

Ciao

Avatar utente
darkstaring
Linux 3.x
Linux 3.x
Messaggi: 639
Iscritto il: mer 13 ott 2010, 13:55
Nome Cognome: Francesco Achenza
Desktop: KDE
Distribuzione: Arch Linux
Contatta:

Re: aiuto query mysql

Messaggio da darkstaring »

Sei stato chiarissimo....cercherò di risolvere con le join...
Allego il db
db.txt
(28.53 KiB) Scaricato 116 volte

Rispondi