|
|
|
![]() |
|
Strumenti |
![]() |
#1 |
Senior Member
Iscritto dal: Jul 2006
Messaggi: 8152
|
[SQL]Fusione di 3 Query. Aiutino?
Ho 3 query che si occupano del calcolo dello stipendio di un ipotetico magazzino:
la prima calcola le ore di lavoro di ogni dipendente e mi restituisce lo stipendio fisso giornaliero di ogni lavoratore, la seconda calcola i depositi di ogni magazziniere e mi restituisce il bonus giornaliero di chi si occupa del deposito e la terza calcola le consegne effettuate e mi restituisce il bonus giornaliero di ogni fattorino, questo viene fatto poichè lo stipendio di ogni dipendente è dato da una quota fissa che dipende dalle ore lavorative e una quota che dipende dalle consegne/depositi effettuati. Calcolo costo fisso: Codice:
SELECT dipendenti.id, dipendenti.tipo, ((lavora.orafine - lavora.orainizio) / 10000) * dipendenti.costoorario AS Fisso FROM dipendenti, lavora WHERE dipendenti.id = lavora.iddipendente AND lavora.data = 090111; Codice:
+----+--------------+-------+ | id | Fisso | Fisso | +----+--------------+-------+ | 1 | Magazziniere | 50 | | 2 | Fattorino | 42 | | 3 | Magazziniere | 48 | | 4 | Fattorino | 49 | +----+--------------+-------+ Codice:
SELECT dipendenti.id, dipendenti.tipo, count(deposita.idmagazziniere) * dipendente.costobonus AS Bonus FROM dipendenti LEFT JOIN deposita ON dipendenti.id = deposita.idmagazziniere AND deposita.datadeposito = 090111 GROUP BY dipendenti.id; Codice:
+----+--------------+-------+ | id | Fisso | Bonus | +----+--------------+-------+ | 1 | Magazziniere | 0.00 | | 2 | Fattorino | 0.00 | | 3 | Magazziniere | 12.00 | | 4 | Fattorino | 0.00 | +----+--------------+-------+ Codice:
SELECT dipendenti.id, dipendenti.tipo, count(ordini.idfattorino) * dipendente.costobonus AS Bonus FROM dipendenti LEFT JOIN ordini ON dipendenti.id = ordini.idfattorino AND ordini.datarichiesta = 090111 GROUP BY dipendenti.id; Codice:
+----+--------------+-------+ | id | Fisso | Bonus | +----+--------------+-------+ | 1 | Magazziniere | 0.00 | | 2 | Fattorino | 3.00 | | 3 | Magazziniere | 0.00 | | 4 | Fattorino | 5.00 | +----+--------------+-------+ Codice:
+----+--------------+---------------+ | id | Fisso | Fisso + Bonus | +----+--------------+---------------+ | 1 | Magazziniere | 50.00 | | 2 | Fattorino | 45.00 | | 3 | Magazziniere | 60.00 | | 4 | Fattorino | 54.00 | +----+--------------+---------------+ ![]() |
![]() |
![]() |
![]() |
#2 |
Member
Iscritto dal: Jan 2009
Città: Forlì
Messaggi: 41
|
Più che le query, è meglio se fai sapere qual'è lo schema del db
![]()
__________________
SATURN: Intel E8400 3.0GHz + Scythe Zipang | Asus P5Q | Kingston 2x2GB DDR2 800MHz | Samsung Spinpoint F1 750GB | Connect3D HD4870 1GB GDDR5 1.8GHz | Cooler Master Sileo 500 + Cooler Master 4-in-3 Module Device + Enermax Pro82+ 525W |
![]() |
![]() |
![]() |
#3 | |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Comunque puoi provare con qualcosa simile a: Codice:
SELECT Query1.id, Query1.tipo, Query1.Fisso + Query2.Bonus + Query3.Bonus FROM Query1 JOIN Query2 ON (Query1.id = Query2.id) JOIN Query3 ON (Query3.id=Query1.id) Codice:
( il codice della X-esima Query che avevi scritto nel tuo post ) AS QueryX
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
![]() |
![]() |
![]() |
#4 | |
Senior Member
Iscritto dal: Jul 2006
Messaggi: 8152
|
Quote:
Dipendente (ID, nome, cognome, telefono, tipo, costo orario, costo bonus) Merci (ID, nome, costo unitario, ricavo unitario, quantità) Ordini (ID, data richiesta, data consegna, ID cliente, ID fattorino, ricavo) Cliente (ID, nome, partita IVA, indirizzo, telefono) Deposita (ID dipendente, ID merce, data deposito, quantità) Contiene (ID ordine, ID merce, quantità) Lavora (ID dipendente, data, ora inizio, ora fine) Ho sottolineato le chiavi. Per Deposita, Contiene e Lavora gli ID sono referenze rispetto alle altre tabelle (sebbene sembra che le referenze non funzionino). In ogni caso grazie per la dritta, ora proverò la query che mi hai consigliato. |
|
![]() |
![]() |
![]() |
#5 |
Member
Iscritto dal: Jan 2009
Città: Forlì
Messaggi: 41
|
Non ho capito bene il tuo obiettivo
![]() Prova a descrivere meglio lo scopo delle tabelle ed esattamente quello che vuoi ottenere a parole ![]() Comunque sia, tieni conto che ci sono certe elaborazioni che non possono essere computate in SQL normale con una sola query (per quanto annidata tu possa farla), ma necessitano estensioni operazionali di SQL (come il PL/SQL di Oracle, ad esempio) che ti permettono di dichiarare cursori e variabili temporanee.
__________________
SATURN: Intel E8400 3.0GHz + Scythe Zipang | Asus P5Q | Kingston 2x2GB DDR2 800MHz | Samsung Spinpoint F1 750GB | Connect3D HD4870 1GB GDDR5 1.8GHz | Cooler Master Sileo 500 + Cooler Master 4-in-3 Module Device + Enermax Pro82+ 525W Ultima modifica di !Piergiorgio : 20-01-2009 alle 19:25. |
![]() |
![]() |
![]() |
#6 | |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Non dico che in assoluto non possa essere, ma non mi ricordo di averne incontrate di non risolvibili con il solo SQL.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
![]() |
![]() |
![]() |
#7 | |
Member
Iscritto dal: Jan 2009
Città: Forlì
Messaggi: 41
|
Quote:
Ma ce ne sono, e anche tante... Tutte quelle che richiedono dei controlli strutturati, ad esempio. Dipende da cosa ci si deve fare ![]() Rimanendo sull'esempio in questione, la computazione che coinvolge query differenti a seconda che la riga in considerazione sia un "fattorino" piuttosto che un "magazziniere" non può essere risolto con una sola query, per quanto si voglia annidare e aggregare. Ci vuole un'esecuzione di query differenziate, una per ogni tipo da considerare, e salvarsi i risultati intermedi. Oppure si usa una delle tante esensioni operazionali di SQL. ![]() http://www.orafaq.com/wiki/PL/SQL_FA...nd_PL.2FSQL.3F
__________________
SATURN: Intel E8400 3.0GHz + Scythe Zipang | Asus P5Q | Kingston 2x2GB DDR2 800MHz | Samsung Spinpoint F1 750GB | Connect3D HD4870 1GB GDDR5 1.8GHz | Cooler Master Sileo 500 + Cooler Master 4-in-3 Module Device + Enermax Pro82+ 525W |
|
![]() |
![]() |
![]() |
#8 |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Sono praticamente certo che la richiesta del thread si possa risolvere con una query abbastanza semplice.
Comunque come siano tante le interrogazioni strutturate per le quali si ha bisogno di programmazione come PL/SQL non riesco proprio a vederlo. So bene cos'e' il PL/SQL, dato che sono certificato sia Oracle che SqlServer, ma tanto complesse da dover essere risolte per forza con PL/SQL, tranne che per esigenze tecniche, non ho mai dovuto affrontarle davvero. Se hai un qualche esempio mi piacerebbe studiarlo.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
![]() |
![]() |
![]() |
#9 |
Member
Iscritto dal: Jan 2009
Città: Forlì
Messaggi: 41
|
Mi viene in mente un tipico esempio:
Codice:
CREATE OR REPLACE PROCEDURE DISCRIMINA_FATTURAZIONE IS CURSOR cursore_importi IS SELECT NUMF,sum(QTA*PREZZO) as IMPORTO FROM dettagli group by NUMF; vr_importi cursore_importi%ROWTYPE; v_TotSmall NUMBER := 0; v_TotBig NUMBER := 0; BEGIN open cursore_importi; LOOP FETCH cursore_importi into vr_importi; EXIT WHEN cursore_importi%NOTFOUND; if vr_importi.IMPORTO < 1000 then v_TotSmall := v_TotSmall + vr_importi.IMPORTO; else v_TotBig := v_TotBig + vr_importi.IMPORTO; end if; END LOOP; close cursore_importi; DBMS_OUTPUT.PUT_LINE('Il totale delle fatture di importo ridotto e'': ' || v_TotSmall); DBMS_OUTPUT.PUT_LINE('Il totale delle fatture di importo elevato e'': ' || v_TotBig); END; Non sono stato a modificare l'esempio per ottenere l'output in forma tabellare, ma è possibile farlo molto facilmente. In questo modo abbiamo lo stesso risultato di "una query che fa quel lavoro lì". Ecco, questa "query che fa quel lavoro lì" non può essere codificata in SQL, non ci sono santi che tengano ![]()
__________________
SATURN: Intel E8400 3.0GHz + Scythe Zipang | Asus P5Q | Kingston 2x2GB DDR2 800MHz | Samsung Spinpoint F1 750GB | Connect3D HD4870 1GB GDDR5 1.8GHz | Cooler Master Sileo 500 + Cooler Master 4-in-3 Module Device + Enermax Pro82+ 525W |
![]() |
![]() |
![]() |
#10 |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Si fa, si fa (sempre se ho capito)
Codice:
SELECT SUM( CASE WHEN Importo<1000 THEN Importo ELSE 0 END) Minori, SUM( CASE WHEN Importo>=1000 THEN Importo ELSE 0 END) Maggiori FROM (SELECT NUMF,sum(QTA*PREZZO) as IMPORTO FROM dettagli group by NUMF) tabtab
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
![]() |
![]() |
![]() |
#11 | |
Member
Iscritto dal: Jan 2009
Città: Forlì
Messaggi: 41
|
Il risultato è quello, ma non è SQL standard.
![]() Quote:
SQL non è un linguaggio turing-completo per definizione ![]()
__________________
SATURN: Intel E8400 3.0GHz + Scythe Zipang | Asus P5Q | Kingston 2x2GB DDR2 800MHz | Samsung Spinpoint F1 750GB | Connect3D HD4870 1GB GDDR5 1.8GHz | Cooler Master Sileo 500 + Cooler Master 4-in-3 Module Device + Enermax Pro82+ 525W Ultima modifica di !Piergiorgio : 21-01-2009 alle 12:07. |
|
![]() |
![]() |
![]() |
#12 | |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Comunque la precedente si puo' risolvere anche in SQL92, con scritture e performance meno efficienti, ma comunque corrette. Codice:
SELECT SUM(SELECT sum(QTA*PREZZO) FROM dettagli group by NUMF HAVING sum(STA*PREZZO) <1000) as MINORI, SUM(SELECT sum(QTA*PREZZO) FROM dettagli group by NUMF HAVING sum(STA*PREZZO) >=1000) as MAGGIORI FROM dual simile, tranne la FROM dual, che occorre omettere.
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
![]() |
![]() |
![]() |
#13 | |
Senior Member
Iscritto dal: Jul 2006
Messaggi: 8152
|
Quote:
Ordini sono gli ordini richiesti da un cliente, contiene pure l'id del fattorino che effettua la consegna. Deposita collega i dipendenti alle merci ed indica quale magazziniere ha effettuato quale merce e in quale data. Contiene collega le merci agli ordini ed indica quante merci ed in quale quantità fanno parte dell'ordine. Lavora indica le ore lavorate per ogni data. Quello che voglio ottenere è lo stipendio di ogni dipendente suddiviso per data. Questo viene calcolato dal numero di ore lavorate per il costo orario sommato al numero di depositi/consegne moltiplicato per il costo bonus. Per ottenerlo con un'unica query dovrei utilizzare un left join dipendenti / ordini e dipendenti / deposita, in modo da ottenere come risultato del bonus il valore 0 nel caso il dipendente non sia del gruppo corretto. (non mi sono spiegato benissimo, il risultato è questo: Codice:
+----+--------------+-------+ | id | Fisso | Bonus | +----+--------------+-------+ | 1 | Magazziniere | 0.00 | | 2 | Fattorino | 0.00 | | 3 | Magazziniere | 12.00 | | 4 | Fattorino | 0.00 | +----+--------------+-------+ Questo è a grandi linee quello che vorrei ottenere. Grazie ![]() |
|
![]() |
![]() |
![]() |
#14 |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Puoi farci un esempio di un ipotetico risultato che vorresti ottenere alla fine, spiegando cosa sono i singoli pezzi?
Mi spiego, restano dubbi come: ti serve una data specifica da inserire nella query oppure no, oppure ti serve un insieme di date specificate nel risultato oppure no, quali sono gli input della query, se ce ne sono (es. costanti come ad esempio una data, oppure un periodo, oppure un mese, etc.etc.)
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
![]() |
![]() |
![]() |
#15 |
Senior Member
Iscritto dal: Jul 2006
Messaggi: 8152
|
L'idea era quella di inserire il comando di query ed ottenere una tabella che mi facesse il riepilogo degli stipendi. Qualcosa del tipo:
"Comando query 10/01/09" ed ottenere: Codice:
+----+--------------+-------+-------+------------+--------+ | id | Tipo | Fisso | Bonus | Data | TOTALE | +----+--------------+-------+-------+------------+--------+ | 1 | Magazziniere | 50 | 10 | 10-01-09 | 60 | | 2 | Fattorino | 42 | 12 | 10-01-09 | 54 | | 3 | Magazziniere | 48 | 11 | 10-01-09 | 59 | | 4 | Fattorino | 49 | 20 | 10-01-09 | 69 | +----+--------------+-------+-------+------------+--------+ Fisso è dato dal numero di ore lavorate nel giorno della query moltiplicato per lo stipendio orario. Bonus è dato dal numero di consegne/depositi effettuati nel giorno della query moltiplicato per il bonus operazione del dipendente. Totale è la somma di Fisso e Bonus. Spero di essere stato chiaro. ---------------------------------------------------------------------- Altre due domandine: sto cercando di inserire delle asserzioni e volevo inserirne una che impedesse l'inserimento di valori nella tabella contiene nel caso la quantità di merci richiesta sia superiore a quella disponibile e contenuta in merci. Ho pensato, invece di creare una ASSERTION, di inserire il check direttamente nella tabella contiene, qualcosa così: Codice:
CREATE TABLE contiene (... IDMerce ... CHECK(contiene.idmerce = (SELECT merci.id FROM merci)) Quantita ... CHECK(contiene.quantita < (SELECT merci.quantita FROM merci)) ... Il codice è corretto visto che la tabella viene perfettamente creata senza errori, solo che non accade nulla inserendo sia un codice merce non esistente, sia una quantità superiore a quella disponibile. Come mai? Ultima domanda (per ora ![]() Ho creato un trigger che dovrebbe diminuire la quantità di merce disponibile dopo ogni inserimento in contiene. Il codice è questo: Codice:
CREATE TRIGGER diminuiscimerce AFTER INSERT ON contiene FOR EACH ROW BEGIN UPDATE merci SET merci.quantita = merci.quantita - contiene.quantita WHERE merci.id = contiene.idmerce END ![]() Ok, basta per ora ![]() |
![]() |
![]() |
![]() |
#16 | |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
Quote:
Hai provato mettendo insieme le query come avevo proposto?
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
|
![]() |
![]() |
![]() |
#17 | |
Senior Member
Iscritto dal: Jul 2006
Messaggi: 8152
|
Quote:
![]() Ho provato a fare come hai detto tu, ma c'è qualcosa che non va con i JOIN. |
|
![]() |
![]() |
![]() |
#18 |
Senior Member
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3692
|
ma hai sostituito tutto correttamente, compresa la parentesi iniziale e quella finale?
Puoi postare il tutto, cosi' vediamo se c'e' qualche errore di sintassi?
__________________
Se pensi che il tuo codice sia troppo complesso da capire senza commenti, e' segno che molto probabilmente il tuo codice e' semplicemente mal scritto. E se pensi di avere bisogno di un nuovo commento, significa che ti manca almeno un test. |
![]() |
![]() |
![]() |
#19 | |
Senior Member
Iscritto dal: Jul 2006
Messaggi: 8152
|
Quote:
Mi cospargo il capo di cenere, avevo sbagliato a scrivere. ![]() Funziona. Vedrò di modificarla per ottenere il risultato senza inserire dentro la query la data. Speriamo di riuscirci... ![]() Grazie ancora. |
|
![]() |
![]() |
![]() |
Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 12:18.