Torna indietro   Hardware Upgrade Forum > Software > Programmazione

DJI Mavic 4 Pro: sblocca un nuovo livello per le riprese aeree
DJI Mavic 4 Pro: sblocca un nuovo livello per le riprese aeree
DJI Mavic 4 Pro porta in dote il nuovo Stabilizzatore Infinity a 360°, che permette nuovi gradi di libertà nelle riprese aeree. Non solo può ruotare a 360 gradi, ma abilita anche riprese dal basso, con inclinazione della videocamera fino a 70°. Il triplo modulo di ripresa offre una fotocamera Hasselblad 28mm con sensore da 100 megapixel e video 6K, ma si spinge fino al teleobiettivo da 50 megapixel e 168mm di focale equivalente. Nuova avionica e batteria per voli fino a 51 minuti di autonomia. La nostra prova
Idrogeno verde in Europa: nuovi studi prevedono costi ben superiori alle aspettative
Idrogeno verde in Europa: nuovi studi prevedono costi ben superiori alle aspettative
Siamo tutti d'accordo: una eventuale diffusione massiccia di idrogeno verde, prodotto esclusivamente da fonti rinnovabili, risolverebbe tanti problemi. Ma siamo ancora lontanissimi da uno scenario del genere e c'entra anche l'Africa. Facciamo il punto della situazione sulla base di studi autorevoli, recentemente pubblicati.
Mario Kart World lancia Switch 2: la magia Nintendo ora in 4K
Mario Kart World lancia Switch 2: la magia Nintendo ora in 4K
Abbiamo provato esaustivamente due dei titoli di lancio della nuova console di Nintendo, il cui debutto è previsto per la settimana in corso. Mario Kart World e Nintendo Switch 2 Welcome Tour si rivelano sorprendenti per certi aspetti e anche perché esaltano alcune delle nuove caratteristiche di Switch 2
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 08-01-2009, 11:45   #1
Donbabbeo
Senior Member
 
L'Avatar di Donbabbeo
 
Iscritto dal: Jul 2006
Messaggi: 8152
[SQL] Query con doppio count: non funge

Premessa: sto svolgendo un piccolo progetto riguardante un magazzino e sono in procinto di creare la query che in base al dipendente da me scelto, ne estrae lo stipendio totale andando a pescare i valori dalle varie tabelle.

Questa è la parte, presa singolarmente che si preoccupa di calcolare la base fissa dello stipendio, che varia in base alle ore:

Codice:
SELECT dipendenti.nome, dipendenti.cognome, count(lavora.iddipendente) * contratti.costoorario 
FROM dipendenti, contratti, stipula, lavora
WHERE dipendenti.iddipendente = 1 AND lavora.iddipendente = 1
AND stipula.iddipendente = 1 AND stipula.idcontratto = contratti.idcontratto;
prende i dati del dipendente dalla tabella dipendenti, le ore di lavoro da lavora e il costo orario dalla tabella contratti, stipula è l'associazione tra dipendenti e contratti. Il dipendente 1, Mario Bianchi, ha lavorato 6 ore e dal suo contratto percepisce 1 euro all'ora. Difatti il risultato della query è questo:

Codice:
+-------+---------+----------------------------------------------------+
| nome  | cognome | count(lavora.iddipendente) * contratti.costoorario |
+-------+---------+----------------------------------------------------+
| Mario | Bianchi |                                               6.00 |
+-------+---------+----------------------------------------------------+
La parte, presa singolarmente che si occupa di calcolare il bonus stipendio è questa:

Codice:
SELECT dipendenti.nome, dipendenti.cognome, count (consegna.idfattorino) * contratti.bonusconsegna
FROM dipendenti, consegna, contratti, stipula
WHERE dipendenti.iddipendente = 1 AND stipula.iddipendente = 1
AND consegna.idfattorino = 1 AND stipula.idcontratto = contratti.idcontratto;
Effettua un lavoro praticamente identico alla precedente, solo che effettua un diverso calcolo, considerando il numero di consegne effettuate e moltiplicandole per il valore nel contratto. Il risultato, considerando che 'sto tizio ha fatto 2 consegne e prende 1 euro a consegna è:

Codice:
+-------+---------+----------------------------------------------------+
| nome  | cognome | count(consegna.idfattorino) * contratti.bonusconsegna |
+-------+---------+----------------------------------------------------+
| Mario | Bianchi |                                               2.00 |
+-------+---------+----------------------------------------------------+
A me purtroppo interessava più che altro avere il TOTALE direttamente su quanto questo povero Cristo prende... Quindi ho creato una query di questo tipo:

Codice:
SELECT dipendenti.nome, dipendenti.cognome, count(lavora.iddipendente) * contratti.costoorario + count(consegna.idfattorino) * contratti.bonusconsegna AS Stipendio
FROM dipendenti, lavora, stipula, contratti, consegna
WHERE dipendenti.iddipendente = 1 AND lavora.iddipendente = 1
AND stipula.iddipendente = 1 AND consegna.idfattorino = 1
AND stipula.idcontratto = contratti.idcontratto;
Mi sarei aspettato come risultato del campo "Stipendio" il valore corretto, cioè 8 €, purtroppo la realtà è ben diversa, ottenendo invece 24 €...
Se provo a separare il count, utilizzando entrambi i campi nella stessa query ottengo per ognuno 12 €. Qualcuno sa da cosa possa derivare l'errore?
Grazie.
__________________
"Quiquid Latine Dictum Sit, Altum Sonatur" 😐
Donbabbeo è offline   Rispondi citando il messaggio o parte di esso
Old 08-01-2009, 11:55   #2
gugoXX
Senior Member
 
L'Avatar di gugoXX
 
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3691
Ci sono 2 problemi.
1.
Probabilmente stai usando un qualche Motore SQL rilassato non standard (MySQL?)
Stai infatti usando una funzione di gruppo (COUNT) senza scrivere un'opportuna clausola GROUP BY.
Per prima cosa ti invito quindi ad aggiungere la clausola GROUP BY, per evitare di incorrere in problemi non deterministici dai quali non si esce piu'.

la cosa migliore sarebbe dedurre i dati che servono lavorando sulla chiave della persona, per poi andare in JOIN con le anagrafiche per prendere nomi, cognomi etc.

2.
La COUNT(campo) semplicemente conta quante righe hanno "campo" diverso da NULL. se vuoi contare quante sono le diverse occorrenze di "Campo", devi usare la
COUNT(DISTINCT campo), non supportata da tutti i motori, e per la quale c'e' pero' un costrutto standard (scomodo) che si puo' usare per supplire alla mancanza.
__________________
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.
gugoXX è offline   Rispondi citando il messaggio o parte di esso
Old 08-01-2009, 13:06   #3
Donbabbeo
Senior Member
 
L'Avatar di Donbabbeo
 
Iscritto dal: Jul 2006
Messaggi: 8152
Esatto, sto usando MySQL, purtroppo sono costretto per "direttive superiori"
Innanzitutto grazie mille per la risposta, più tardi cercherò di correggere la funzione.
C'è una cosa però del tuo discorso che non ho capito:
la cosa migliore sarebbe dedurre i dati che servono lavorando sulla chiave della persona, per poi andare in JOIN con le anagrafiche per prendere nomi, cognomi etc.

Non è quello che ho fatto?
Magari in realtà si fa in altro modo, io sto seguendo solo queste mie "direttive" ... Sono curioso, se ti fosse possibile vorrei vedere un tuo esempio.

Comunque grazie
__________________
"Quiquid Latine Dictum Sit, Altum Sonatur" 😐
Donbabbeo è offline   Rispondi citando il messaggio o parte di esso
Old 08-01-2009, 14:20   #4
Donbabbeo
Senior Member
 
L'Avatar di Donbabbeo
 
Iscritto dal: Jul 2006
Messaggi: 8152
Ok, non picchiarmi, ma sto riprovando a modificare la query...

La count non funziona con la distinct, cioè a me serve proprio di contare tutte le occorrenze non null, visto che tramite i vari join ottengo già la scrematura delle varie righe eventualmente ripetute che possono presentarsi.

Mentre per la group by: l'ho inserita senza ottenere alcuna variazione del risultato...
Considerando l'uso di due count nella stessa query... su quale dovrei usare la group by? (Non credo sia possibile usare 2 group by nella stessa query, o perlomeno non ne ho trovato alcuna traccia sulla mia documentazione)

Il finale è sempre lo stesso: il risultato è sempre uguale, cioè non torna, sto provando tutte le modifiche possibili che il mio piccolo cervellino riesce a ponderare, ma non c'è storia
__________________
"Quiquid Latine Dictum Sit, Altum Sonatur" 😐
Donbabbeo è offline   Rispondi citando il messaggio o parte di esso
Old 08-01-2009, 14:22   #5
gugoXX
Senior Member
 
L'Avatar di gugoXX
 
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3691
Quote:
Originariamente inviato da Donbabbeo Guarda i messaggi
Esatto, sto usando MySQL, purtroppo sono costretto per "direttive superiori"
Innanzitutto grazie mille per la risposta, più tardi cercherò di correggere la funzione.
C'è una cosa però del tuo discorso che non ho capito:
la cosa migliore sarebbe dedurre i dati che servono lavorando sulla chiave della persona, per poi andare in JOIN con le anagrafiche per prendere nomi, cognomi etc.

Non è quello che ho fatto?
Magari in realtà si fa in altro modo, io sto seguendo solo queste mie "direttive" ... Sono curioso, se ti fosse possibile vorrei vedere un tuo esempio.

Comunque grazie
Per poter scrivere una query corretta occorre conoscere lo schema del DB, compresi se soprattutto i constraint come le chiavi primarie.
P.Es., se ogni fattorino potesse stipulare piu' di un contratto, ciascuno con il suo bonusconsegna, cosa vorresti fare?

Se p.es ce n'e' uno solo di sicuro, perche' la chiave primaria di contratti e' IDfattorino, oppure perche' c'e' un vincolo di unicita' sopra, una delle possibili scritture potrebbe essere

Query1: (Per ottenere le ore lavorate da ciascun dipendente)
Codice:
SELECT iddipendente,COUNT(*) orelavorate
FROM lavora
GROUP BY iddipendente
Query2: (Per ottenere i colli consegnati da ciascun fattorino)
Codice:
SELECT idfattorino,COUNT(*) colli
FROM consegna
GROUP BY idfattorino
La JOIN completa (ove bisogna sostituire le query precedenti al posto di Query1 e Query2, ovvero aprire la parentesi tonda, scrivere la query relativa e mettere l'alias)

Codice:
SELECT dipendenti.nome, dipendenti.cognome, query1.orelavorate * contratti.costoorario + query2.colli * contratti.bonusconsegna AS Stipendio
FROM dipendenti, lavora, contratti, Query1, Query2
WHERE  lavora.iddipendente = dipendenti.iddipendente
  AND query1.iddipendente =dipendenti.iddipendente
  AND query2.idfattorino =  dipendenti.iddipendente 
  AND stipula.iddipendente = dipendenti.iddipendente 
  AND stipula.idcontratto = contratti.idcontratto;
ovvero, alla fine, se il vincolo e' confermato e se non ho fatto errori

Codice:
SELECT dipendente.iddipendente, dipendenti.nome, dipendenti.cognome, query1.orelavorate * contratti.costoorario + query2.colli * contratti.bonusconsegna AS Stipendio
FROM dipendenti, lavora, stipula, contratti, 
   ( SELECT iddipendente,COUNT(*) orelavorate
          FROM lavora
          GROUP BY iddipendente  ) AS Query1,
   (   SELECT idfattorino,COUNT(*) colli
           FROM consegna
          GROUP BY idfattorino
    ) AS Query2
WHERE  lavora.iddipendente = dipendenti.iddipendente
  AND query1.iddipendente =dipendenti.iddipendente
  AND query2.idfattorino =  dipendenti.iddipendente 
  AND stipula.iddipendente = dipendenti.iddipendente 
  AND stipula.idcontratto = contratti.idcontratto;
se crei una vista di quella roba li', potrai scrivere alla fine
SELECT * FROM MiaVista WHERE iddipendente=1



e se al posto di usare le JOIN cosi', usi le JOIN corrette, ovvero la sintassi

FROM dipendenti JOIN lavora ON ( lavora.iddipendente = dipendenti.iddipendente)

per tutte le join, e' ancora meglio.
__________________
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.
gugoXX è offline   Rispondi citando il messaggio o parte di esso
Old 08-01-2009, 14:36   #6
Donbabbeo
Senior Member
 
L'Avatar di Donbabbeo
 
Iscritto dal: Jul 2006
Messaggi: 8152
wow, non c'è che dire, non so nulla di sql

Vedrò di fare una profonda revisione dell'intero database
__________________
"Quiquid Latine Dictum Sit, Altum Sonatur" 😐
Donbabbeo è offline   Rispondi citando il messaggio o parte di esso
Old 08-01-2009, 15:03   #7
Donbabbeo
Senior Member
 
L'Avatar di Donbabbeo
 
Iscritto dal: Jul 2006
Messaggi: 8152
Ti amo.

Ora funziona correttamente!

PS: nella query completa manca il group by dipendenti.iddipendente alla fine giusto?

Spero di non doverti più disturbare ma ne dubito
__________________
"Quiquid Latine Dictum Sit, Altum Sonatur" 😐
Donbabbeo è offline   Rispondi citando il messaggio o parte di esso
Old 08-01-2009, 15:08   #8
gugoXX
Senior Member
 
L'Avatar di gugoXX
 
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3691
No, nella query completa non serve alcun Group by, essendo che non sono coinvolte funzioni di gruppo.
__________________
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.
gugoXX è offline   Rispondi citando il messaggio o parte di esso
Old 12-01-2009, 14:28   #9
Donbabbeo
Senior Member
 
L'Avatar di Donbabbeo
 
Iscritto dal: Jul 2006
Messaggi: 8152
Come era ovvio, durante la revisione dell'intero database, ho trovato qualche problema in alcune funzioni che finora sono definite solo nella mia testolina bacata...

Bene o male son riuscito a passare sopra tutto, ma sembra che non riesca invece a risolvere questa particolare Query...

La situazione è "abbastanza" semplice e la descrivo con questa mini-tabellina doppia:

Codice:
		PIPPO		PLUTO		PAPERINO
MARIO		5		4		1
GUIDO		10		3		1
GIACOMO		2		2		1
MARCO		3		1		5
In pratica stiamo parlando dei magazzinieri, e qui riassunti abbiamo i vari magazzinieri con le quantita di merci depositate per tipo (come si intuisce dai loro nomi sono merci di fantasia ).
Il mio desiderio era ottenere come risultato della query una tabella che mi restituisca per ogni dipendente l'elenco dei prodotti e il conto totale, ma sembra che non ne sia capace...

Posso ottenerla per un singolo dipendente (in pratica ottengo una singola riga di questa tabella a doppia entrata) ma non riesco a farlo per tutti i dipendenti contemporaneamente. Io vorrei qualcosa così:

Codice:
+----------------+---------+----------+
| idmagazziniere | idmerce | count(*) |
+----------------+---------+----------+
|              1 |       1 |        5 |
|              1 |       2 |        4 |
|              1 |       3 |        1 |
|              2 |       1 |       10 |
|              2 |       2 |        3 |
|              2 |       3 |        1 |
|              3 |       1 |        2 |
|              3 |       2 |        2 |
|              3 |       3 |        1 |
|              4 |       1 |        3 |
|              4 |       2 |        1 |
|              4 |       3 |        5 |
+----------------+---------+----------+
E' possibile? Il problema sembra risiedere nel fatto di dover utilizzare l'istruzione group by, poiche se raggruppo per dipendenti otterrò 4 righe con la somma dei depositi dei vari tipi per ciascun magazziniere, mentre se raggruppo per merce ottengo il totale disponibile per ciascuna merce...
__________________
"Quiquid Latine Dictum Sit, Altum Sonatur" 😐
Donbabbeo è offline   Rispondi citando il messaggio o parte di esso
Old 12-01-2009, 14:53   #10
gugoXX
Senior Member
 
L'Avatar di gugoXX
 
Iscritto dal: May 2004
Città: Londra (Torino)
Messaggi: 3691
Il problema sta nella tabella. Quella sembra essere una tabella risultato di quache processo di reportistica, dato che non e' una tabella relazionale corretta.
Cosa accadrebbe infatti a quella tabella se saltasse fuori un nuovo prodotto in azienda?
Cerca se per caso esiste una tabella sorgente dei dati, che dovrebbe fra l'altro gia' essere in una forma simile a quello che desideri.
__________________
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.
gugoXX è offline   Rispondi citando il messaggio o parte di esso
Old 12-01-2009, 15:26   #11
Donbabbeo
Senior Member
 
L'Avatar di Donbabbeo
 
Iscritto dal: Jul 2006
Messaggi: 8152
Innanzitutto grazie per la rapidità con cui rispondi

Ovviamente quel risultato è ottenuto dalla combinazione di 3 tabelle: la tabella dei dipendenti da cui prendo i dati sui dipendenti come nome e cognome (attualmente c'è solo l'id perchè sono pigro e finchè non è corretto non lo scrivo ), la tabella delle merci da cui prendo i dati sulle merci (nel caso specifico solo il nome, stesso discorso qui sopra, il nome ce lo segno solo quando sarà corretto) e una tabella che mi tiene in relazione i depositi, nella quale ad ogni riga associa l'id dipendente ad un id merce e indica l'ora in cui viene eseguita l'operazione. In pratica se il dipendente A deposita 5 merci B, nella tabella risulteranno 5 nuove tuple di questo tipo :
Codice:
(A, B, 2009-01-12 16:18:10)
Ovviamente ciascuna nuova tupla avrà un valore di secondi differente e in questa tabella per evitare ciascuna possibile ridondanza la chiave primaria è formata dalla combinazione di tutti e 3 i valori.
Ne consegue che per calcolare le merci depositate da un dipendente non posso semplicemente pescare il numero di merci depositate, visto che tale valore non è memorizzato e quindi sono obbligato ad effettuare il count per conoscere quante merci deposita un qualsiasi magazziniere. Probabilmente non è un sistema efficiente, ma è il primo che mi è venuto in mente che si integrasse con il database

Alternativamente potrei aggiungere un campo ai dipendenti in cui tengo conto del numero di merci depositate e ad ogni nuova interazione verrebbe aggiornato tramite un trigger, ma non credo cambi poi molto, visto che farebbe una semplice "somma bruta" dei depositi di ciascun dipendente.
__________________
"Quiquid Latine Dictum Sit, Altum Sonatur" 😐
Donbabbeo è offline   Rispondi citando il messaggio o parte di esso
Old 19-04-2010, 08:22   #12
magmahell
Junior Member
 
Iscritto dal: Apr 2010
Messaggi: 1
Ciao, sarei interessato a creare una visualizzazione simile alla tua riportata qui sopra, potresti postare la query che hai utilizzato per realizzarla.

grazie!

magmahell è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


DJI Mavic 4 Pro: sblocca un nuovo livello per le riprese aeree DJI Mavic 4 Pro: sblocca un nuovo livello per le...
Idrogeno verde in Europa: nuovi studi prevedono costi ben superiori alle aspettative Idrogeno verde in Europa: nuovi studi prevedono ...
Mario Kart World lancia Switch 2: la magia Nintendo ora in 4K Mario Kart World lancia Switch 2: la magia Ninte...
La rivoluzione dei dati in tempo reale è in arrivo. Un assaggio a Confluent Current 2025 La rivoluzione dei dati in tempo reale è ...
SAP Sapphire 2025: con Joule l'intelligenza artificiale guida app, dati e decisioni SAP Sapphire 2025: con Joule l'intelligenza arti...
Scambio di chiavi quantistico via satell...
HONOR 400 è un successo! Forte sl...
Redmi Pad 2, i nuovi tablet Xiaomi costa...
All'aeroporto di Fiumicino il più...
HONOR 400 vs HONOR 400 Pro: tutte le dif...
Nintendo Switch 2 debutta oggi nei negoz...
Samsung Galaxy S25 Edge è disponi...
Nothing presenterà le sue prime c...
Le nuove soluzioni Lenovo per lo storage...
Netatmo presenta la nuova Stazione Meteo...
Cybersecurity: Fortinet rende disponibil...
Netatmo Stazione Meteo ORIGINAL: il rito...
Il meglio dello State of Play, dal nuovo...
Homematic IP: nuova app per ottimizzare ...
Logitech G Astro A30 LIGHTSPEED in offer...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 02:39.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
Served by www2v