Query con differenza tra record della stessa tabella accomunati da un ...

martedì 18 marzo 2014 - 15.17
Tag Elenco Tags  SQL Server 2008 R2  |  SQL Server 2008  |  SQL Server 2005  |  SQL Server 2000  |  SQL Server Express

Bolo Profilo | Junior Member

Ciao a tutti, devo fare una query particolare ma non riesco ad uscirne vivo:

Ho una tabella con una serie di orari di ingresso e uscita collegati a un codice turno (quindi ogni turno avrà due record, so che è scorretto a livello di database, ma sono vincolato a una serie di cose).

Vorrei raggruppare per turno gli orari e calcolare il DATEDIFF, come posso fare?

Ho provato con:
select prv_code, datediff (hh, (select prv_dvalue from R5PROPERTYVALUES where PRV_PROPERTY = 'UTNCIN'), (select prv_dvalue from R5PROPERTYVALUES where PRV_PROPERTY = 'UTNCOUT')) from R5PROPERTYVALUES group by prv_code

Ma mi restituisce l'errore "La subquery ha restituito più di un valore".
Probabilmente è una cavolata, ma non ci riesco...

Grazie

renarig Profilo | Expert

>Ciao a tutti, devo fare una query particolare ma non riesco ad uscirne vivo:
Esagerato !!



>Ma mi restituisce l'errore "La subquery ha restituito più di un valore".
Dalla query che ci posti e da quello che dici direi che la tabella è fatta cosi:

R5PROPERTYVALUES
prv_code -------- Testo ----- il turno puoi/devi avere max 2 record con lo stesso prv_code
prv_dvalue ------ DataOra ---- l'orario che puo essere indifferentemente ingresso o uscita
PRV_PROPERTY --- Testo -- è una specie di Booleano che ammette UTNCIN o UTNCOUT ( ingresso o uscita )


Ti restituisce quell'errore perche effettivamente la sottoquery restituisce piu di un valore,
guardala bene
-- (select prv_dvalue from R5PROPERTYVALUES where PRV_PROPERTY = 'UTNCIN')
di valori con UTNCIN ne hai 1 per ogni prv_code !!!!!

NB: Ti ricordo che TUTTE le sottoquery non possono restituire piu di 1 valore semplicemente
perche il risultato deve poi entrare in una singola "cella"

Potresti risolverlo cosi
Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

ma io ( semplicemente per simpatia ) lo farei cosi:
e non ti servirebbe neanche il campo PRV_PROPERTY perche lo desumi dal Min e Max
SELECT R5PROPERTYVALUES.prv_code, Min(R5PROPERTYVALUES.prv_dvalue) AS Ingx, Max(R5PROPERTYVALUES.prv_dvalue) AS Uscx, DateDiff("h",Min([R5PROPERTYVALUES].[prv_dvalue]),Max([R5PROPERTYVALUES].[prv_dvalue])) AS Difx FROM R5PROPERTYVALUES GROUP BY R5PROPERTYVALUES.prv_code ;

Facci sapere

.

Bolo Profilo | Junior Member

Fantastico!!!

Ho risolto in un micro secondo con la soluzione 2 che sta più simpatica pure a me

Si dai, forse con l' "uscirne vivo" avevo un attimo esagerato ma era per stimolare la discussione

Grazie per la soluzione ma soprattutto per i preziosi insegnamenti e buona giornata

Bolo Profilo | Junior Member

Rieccomi con una nuova problematica collegata a quanto sopra...

Ora vorrei fare la somma dei vari datediff...

con questa query mi trovo il mio bel elenco di turni con le colonne anno, mese, descrizione e ore lavorate:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Vorrei sommare i valori delle ore lavorate raggruppati per anno e mese, ho provato con un timido sum (datediff....) ma ahimè non funziona perchè dice che devo raggruppare, ma provando a raggruppare i campi prv_code non funziona ancora... devo rivoluzionare il tutto o basta qualche piccolo accorgimento?

Grazie anticipatamente, Maurizio

renarig Profilo | Expert

In questo momento non ho un SQLServer per testare,

ma penso che se lo fai cosi dovrebbe andare:
Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Magari se non va postaci lo script delle 3 tabele interessate con relazioni e un po di dati
che ci "divertiamo" un po in serata

Ho gia la sensazione che sia tutto un po "arrangiaticcio",

Io ti avevo proposto un degli Allias ( T1 ) ipotizzando che avevi solo 1 tabella di origine,
adesso vedo che le tabelle in effetti sono 3 e le altre 2 sono rimaste senza Allias,
-- Non dico che è sbagliato, ma pero.....

poi davanti al nome dei campi io sono abituato a scrivere sempre
il nome della tabella ( o il suo Allias )
-- non è sbagliato non metterli, ma ....
se dovessi ricostruire le tabelle dala query non sarebbe possibile

.

Bolo Profilo | Junior Member

Purtroppo non funziona e da lo stesso errore che dava a me, ovvero il solito

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Inserire lo script delle tabelle mi riesce difficile visto che per dire la R5EVENTS ha 723 righe... comunque posso riassumere quanto serve cercando di semplificare:

TABELLA R5EVENTS (contiene i turni)
Campi di interesse: EVT_CODE (codice del turno) - EVT_TARGET (data del turno) - EVT_JOBTYPE ( codice del tipo di turno)

TABELLA R5PROPERTYVALUES (contiene i dati di timbratura del turno)
Campi di interesse: PRV_CODE (turno di riferimento) - PRV_PROPERTY (tipo timbratura, ingresso (UTNCIN) o uscita (UTNCOUT)) - PRV_DVALUE (orario timbratura)
Relazioni: EVT_CODE -> PRV_CODE one to many

TABELLA R5UCODES (codifica la tipologia di turno)
Campi di interesse: UCO_CODE (codice del tipo di turno) - UCO_DESC (descrizione del tipo di turno)
Relazioni: UCO_CODE -> EVT_JOBTYPE one to one

Spero sia sufficientemente esaustivo.

Confermo che è tutto un pò arrangiaticcio a livello di query mentre il database è tutt'altro che arrangiaticcio, solo che essendo a supporto di un software complesso totalmente parametrico, ha circa 800 tabelle, trigger ecc ecc e io devo tirar fuori 4 dati in croce per grafici e KPI... ecco svelato l'arcano

renarig Profilo | Expert

> ..... Spero sia sufficientemente esaustivo. ......
Non hai messo i formati dei campi e le Key
ma la fantasia ci aiuta ......


>Msg 130, Level 15, State 1, Line 1
>Impossibile eseguire una funzione di aggregazione su un'espressione
>contenente un'aggregazione o una subquery.
Ma perche non scegli la strada piu facile senza subquery ??
( è piu facile da eseguirsi anche per il motore del DB )
Provalo cosi, magari al prossimo colpo vedremo di farlo anche con le SubQuery
SELECT YEAR(T2.EVT_TARGET) AS anno, MONTH(T2.EVT_TARGET) AS mese, T3.UCO_DESC, MIN(T1.PRV_DVALUE) AS Minx, MAX(T1.PRV_DVALUE) AS Maxx, CAST(DATEDIFF(mi, MIN(T1.PRV_DVALUE), MAX(T1.PRV_DVALUE)) AS FLOAT(2)) / 60 AS SommaOre, CAST(MAX(T1.PRV_DVALUE) - MIN(T1.PRV_DVALUE) AS FLOAT(2)) * 24 AS Alternativa2EspressaInOre, CAST(MAX(T1.PRV_DVALUE) - MIN(T1.PRV_DVALUE) AS FLOAT(2)) AS Alternativa3EspressaInGiorni FROM dbo.R5EVENTS AS T2 INNER JOIN dbo.R5PROPERTYVALUES AS T1 ON T1.PRV_CODE = T2.EVT_CODE INNER JOIN dbo.R5UCODES AS T3 ON T3.UCO_CODE = T2.EVT_JOBTYPE GROUP BY YEAR(T2.EVT_TARGET), MONTH(T2.EVT_TARGET), T3.UCO_DESC


>Confermo che è tutto un pò arrangiaticcio a livello di query
>mentre il database è tutt'altro che arrangiaticcio, solo che
>essendo a supporto di un software complesso totalmente parametrico,
>ha circa 800 tabelle, trigger ecc ecc e io devo tirar fuori 4
>dati in croce per grafici e KPI... ecco svelato l'arcano
Io avrei PAURA su un DB che non conosco approfonditamente a metterci dentro
delle query che stai ancora testando, certamente lavori su un BackUp .....

Perche non pensi nella stessa istanza dove risiede il DB principale a farti un "MiniDataBase"
con le tabele collegate al DB Principale ?????
o meglio a conneterti con la applicazione che ti fara i grafici e fare tutto li ???

A quel punto potresti "giocare" a casa tua

.

Bolo Profilo | Junior Member

Ciao!!!

In realtà la strada senza sub query era veramente bella, peccato che senza subquery mi fa la differenza tra il min e il max di tutti i valori raggruppati, ovvero mi da la differenza in ore tra la prima timbratura in ingresso e lìultima in uscita per il gruppo di turni di quel tipo/anno/mese.
Con la subquery e senza il sum invece mi fa vedere correttamente l'elenco dei turni, inserendo il sum però mi da l'errore solito

Che rischio corro con delle query di sola lettura? Di certo non mi metto a scrivere su quel db, anche perchè l'ho già fatto una volta e mi è bastato
Comunque lo scopo di questa query è tirare fuori i dati che verranno visualizzati su un grafico, e appena pronta la inserisco in un form del sistema configurata come vuole lui (ovvero 4 colonne, la prima anno, la seconda mese, la terza tipologia e la quarta valore).

Certo pensavo venisse una query di 4 righe

renarig Profilo | Expert

>In realtà la strada senza sub query era veramente bella, peccato
>che senza subquery mi fa la differenza tra il min e il max di
>tutti i valori raggruppati, .....
è vero sono stato "stupidino" , questa sera pero ce la faremo


>Che rischio corro con delle query di sola lettura? Di certo non
>mi metto a scrivere su quel db, anche perchè l'ho già fatto una
>volta e mi è bastato
In teoria nessun rischio,
ma in pratica stai manovrando al cuore di un sistema che non conosci pienamente
se poi il Server ti va in tilt perche si bruciano i 2 alimentatori diventa
colpa tua perche la tua query consuma troppa corrente quando si esegue

Poi effettivamente è meglio far fare al DataBase il suo lavoro di conservare e rendere disponibile la Base dei Dati
i diagrammi con tutto quanto necessario per calcolarli posssono stare piu felicemente nella applicazione

.

Bolo Profilo | Junior Member

Tanto è sempre colpa mia... anche se non faccio le cose quindi a sto punto le faccio così mi diverto... i grafici riassuntivi, KPI,ecc ecc sono la mia perversione, cosa vuoi farci

renarig Profilo | Expert

o sono troppo stanco oppure c'è qualcosa di fugace nella struttura che ci descrivi !!

Dicci di quelle 3 tabelle oltre ai nomi dei campi e le relazioni che gia sappiamo
anche quali sono le Key Univoche e non


Magari facci un esempio di pochi record significativi sulle 3 tabelle con relativo risultato desiderato.

Bolo Profilo | Junior Member

Provo a semplificare incollando la query che può essere ottimo punto di partenza per raggiungere il mio obbiettivo e il risultato che da:

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

Questa query mi restituisce una tabella del tipo:

Anno Mese Tipo turno Codice turno Ore lavorate
2013 5 UTNTS 80119 6
2013 5 UTNTO 80272 4
2013 5 UTNTO 80296 5
2013 5 UTNTO 80297 5
2013 5 UTNTO 80298 5
2013 5 UTNTO 80300 3
2013 5 UTNTS 80307 5
2013 5 UTNTO 80299 5
2013 5 UTNTO 80302 3
2013 5 UTNTS 80316 6
2013 5 UTNTS 80312 0
2013 5 UTNTO 80357 3
2013 5 UTNTO 80305 1
2013 5 UTNTO 80306 1
2013 5 UTNTO 80366 6
2013 5 UTNTO 80367 3
2013 5 UTNTS 80308 5
2013 5 UTNTO 80368 6

Ora, fregandomene del codice turno (che ho lasciato solo per far capire che ogni riga è un turno diverso) vorrei sommare le ore e vederle suddivise per anno, mese e tipo turno.

Ce la faranno i nostri eroi?

Bolo Profilo | Junior Member

Sono riuscito, magari in maniera poco elegante, però funziona

Il codice sorgente non è stato renderizzato qui
perchè non c'è sufficiente spazio.
Clicca qui per visualizzarlo in una nuova finestra

A forza di sbatterci la testa qualcosa viene fuori
Partecipa anche tu! Registrati!
Hai bisogno di aiuto ?
Perchè non ti registri subito?

Dopo esserti registrato potrai chiedere
aiuto sul nostro Forum oppure aiutare gli altri

Consulta le Stanze disponibili.

Registrati ora !
Copyright © dotNetHell.it 2002-2025
Running on Windows Server 2008 R2 Standard, SQL Server 2012 & ASP.NET 3.5