Calcolare la differenza tra due valori nella stessa colonna in righe s...

giovedì 15 maggio 2008 - 14.04

paovanm Profilo | Junior Member

Sono sempre qui... ed ho sempre il mio dtabase sql server...

Ora il mio problema è cercare di calcolare la differenza tra due valori della stessa colonna ma in righe successive...

ID | Ore motore su banco | ore prova
____________________________
1 0
2 150
3 320

Vorrei che in ore prova venisse calcolata la differenza tra ([ore motore su banco] where ID=2) - ([ore motore su banco] where ID=1)

Ho provato ad assegnare loro dei parametri, tipo un valore = A e l'altro =B e chiedere che in Ore prova venisse assegnato il valore B-A usando l'istruzione set ma non mi torna nulla...

Any suggestions?

Grazie
Michela


alx_81 Profilo | Guru

>Sono sempre qui... ed ho sempre il mio dtabase sql server...
Ciao Michela!

>
>Ora il mio problema è cercare di calcolare la differenza tra
>due valori della stessa colonna ma in righe successive...
>Vorrei che in ore prova venisse calcolata la differenza tra ([ore
>motore su banco] where ID=2) - ([ore motore su banco] where ID=1)
>Any suggestions?
Ma vuoi che venga fatta una differenza a due a due? Oppure che venga fatta la differenza tra i primi due, poi la differenza tra il risultato delle prime due meno la terza, e così via?

Potresti postare la create table della tua tabella, fornirci qualche insert ed il risultato che vuoi ottenere?
Grazie!


Alessandro Alpi | SQL Server MVP

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi
http://italy.mvps.org

paovanm Profilo | Junior Member

Dovrebbe essere sempre una differenza tra due valori, tra uno ed il precedente.

Grazie,
Michela

alx_81 Profilo | Guru

>Dovrebbe essere sempre una differenza tra due valori, tra uno
>ed il precedente.
Ok, ora mancano un paio di informazioni ancora:

- Quale versione di SQL Server hai? 2005?
- Qual è l'ordinamento secondo cui un record viene prima dell'altro (o comunque l'ordinamento in generale)?
- Puoi postare qualche insert di prova e il risultato che effettivamente vuoi ottenere? Perchè se hai due record, in ore prova vi sarà sempre la differenza?
>
>Grazie,
di nulla!
Alessandro Alpi | SQL Server MVP

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi
http://italy.mvps.org

paovanm Profilo | Junior Member

ID | Ore motore su banco | ore prova
____________________________
1 0 0
2 150 150
3 320 170

Io sto usand SQL 2000 ma sono in atesa dell'upgrade al 2005.

I record sono ordint in ordine cronologico. ID rappresenta un test che deve fare un det motore che consiste in tot ore di prova (ore motore su banco). nel id 2 (seconda prova) il motore accumula altre ore che si sommano alle precenti. Io vorrei sapere le ore che il motore fa per la singola prova che si ottengono quindi dalla differenza tra le oe del motore sul banco di un certi ID - le ore del motore nell'ID successivo.

Sì, in ore di prova dovrebbe essereci sempre il risultato di una differneza.

Grazie,

Michela


paovanm Profilo | Junior Member

Scusate ma sono semre qui con il mio problema di calcolo... che oltretutto mi blocca il lavoro (sig., sig...)

Ho provato con questa procedura:
CREATE PROCEDURE spCONTI @Matricola char(10), @rev1 smallint = 0, @rev2 smallint = 0
AS
BEGIN
SELECT [02_Assempling/Durability].[Ore motore sul banco] as [A] into tab2 FROM [02_Assempling/Durability] INNER JOIN [01_Project/Engine Information] ON [02_Assempling/Durability].[ID motore]=[01_Project/Engine Information].[ID motore] WHERE [Matricola (SN)] = @Matricola and [Revisione] = @rev1
SELECT [02_Assempling/Durability].[Ore motore sul banco] As [B] into tab2 FROM [02_Assempling/Durability] INNER JOIN [01_Project/Engine Information] ON [02_Assempling/Durability].[ID motore]=[01_Project/Engine Information].[ID motore] WHERE [Matricola (SN)] = @Matricola and [Revisione] = (@rev1+1)
END

Dove praticamente cerco di creare una nuova tabella tab2 nelle cui righe (A, B, etc...) vorrei distribuire i valori di cui vorrei fare la differenza che nella tabella originale sono in colonna (perchè temporalmente successivi)...

La procedura viene creata correttamente ma, quando la cerco di eseguire mi ritorna solo la colonna A, la seconda colonna non viene creata ed ho il seguante messaggio di errore:

(righe interessate: 1)

Server: messaggio 2714, livello 16, stato 6, procedura spCONTI, riga 5
Il database include già un oggetto denominato 'tab2'.

UFFI!!

come posso ovviare?????

Grazie in advance
Michela

alx_81 Profilo | Guru

>Scusate ma sono semre qui con il mio problema di calcolo... che
>oltretutto mi blocca il lavoro (sig., sig...)
Vista l'urgenza mi sono trovato un pochino di tempo
>
>Ho provato con questa procedura:
>La procedura viene creata correttamente ma, quando la cerco
>di eseguire mi ritorna solo la colonna A, la seconda colonna
>non viene creata ed ho il seguante messaggio di errore:
Questo perchè la INTO crea fisicamente la tabella, e se la ripeti due volte, cerchi di creare una tabella che c'è già.
>
>come posso ovviare?????
Osserva il seguente esempio:

E' per sql server 2000, ma vedrai anche una variazione per sql server 2005 commentata.
Provala e fammi sapere

USE tempdb; GO -- creazione oggetti CREATE TABLE dbo.OreLavoro ( ID int NOT NULL PRIMARY KEY CLUSTERED , OreSuBanco smallint NOT NULL ) GO INSERT INTO dbo.OreLavoro (ID, OreSuBanco) VALUES (1, 0) INSERT INTO dbo.OreLavoro (ID, OreSuBanco) VALUES (2, 150) INSERT INTO dbo.OreLavoro (ID, OreSuBanco) VALUES (3, 320) INSERT INTO dbo.OreLavoro (ID, OreSuBanco) VALUES (5, 400) INSERT INTO dbo.OreLavoro (ID, OreSuBanco) VALUES (7, 500) GO -- siccome gli id potrebbero non essere in sequenza, genero un contatore DECLARE @t TABLE (ID int, IndiceRiga int, OreSuBanco int) -- VERSIONE per SQL SERVER 2005 - Funzione ROWNUMBER() /********************************************************************* INSERT INTO @t SELECT ID , IndiceRiga = ROW_NUMBER() OVER (ORDER BY ID) , OreSuBanco FROM dbo.OreLavoro **********************************************************************/ -- VERSIONE per SQL SERVER 2000 -- ********************************************************************* INSERT INTO @t SELECT ID , (SELECT COUNT(*) FROM dbo.OreLavoro O2 WHERE O2.ID <= O1.ID) as IndiceRiga , O1.OreSuBanco FROM dbo.OreLavoro O1 -- ********************************************************************** SELECT * FROM @t -- ricavo la sottrazione SELECT O1.ID , O1.IndiceRiga , O1.OreSuBanco - ISNULL(O2.OreSuBanco,0) FROM @t O1 LEFT JOIN @t O2 ON O1.IndiceRiga = O2.IndiceRiga + 1 -- pulizia DROP TABLE dbo.OreLavoro GO
>
>Grazie in advance
Di nulla!
Alessandro Alpi | SQL Server MVP

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi
http://italy.mvps.org

paovanm Profilo | Junior Member

Grazie mille ora studio il tuo esempio e ti dico!!
Anche io avevo quasi trovata una strada alternativa... da completare ed un po' contorta forse... Appena finisco ti dico

Grazie!!

alx_81 Profilo | Guru

>Grazie mille ora studio il tuo esempio e ti dico!!
>Anche io avevo quasi trovata una strada alternativa... da completare
>ed un po' contorta forse... Appena finisco ti dico
Il vantaggio della soluzione che ti ho proposto è che evita logiche particolari come cicli e cursori..
Quindi ti consiglio di ragionare sempre SET BASED
>
>Grazie!!
Di nulla!

Alessandro Alpi | SQL Server MVP

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi
http://italy.mvps.org

paovanm Profilo | Junior Member

Infatti io volevo impostare una sorta di ciclo con un while, ma mi sono effettivamente persa...

Ho capito perfettamente il tuo esempio, ora lo adatto al mio caso!!
.. (Ma perchè a me non vengono mai cose così?????!!)

Grazie ancora tantissimo!
Michela

alx_81 Profilo | Guru

>Infatti io volevo impostare una sorta di ciclo con un while,
>ma mi sono effettivamente persa...
è andata bene.. appena in tempo
>
>Ho capito perfettamente il tuo esempio, ora lo adatto al mio
>caso!!
Bene

>.. (Ma perchè a me non vengono mai cose così?????!!)
Eheheh.. ci vuole un po' di tempo a ragionare SET BASED e non è facile per niente..
>
>Grazie ancora tantissimo!
Figurati. Ricordati di accettare la risposta così chiudiamo il thread.
Ciao!
Alessandro Alpi | SQL Server MVP

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi
http://italy.mvps.org

paovanm Profilo | Junior Member

Ciao,

scusa ma credevo di avere capito il tuo esempio, ma cercandolo di addattarlo alla mia situazione mi sono accorda che ho dei dubbi! In particolare:
Nalla fase di ordinamento e dove viene eseguita la sottrazione ho notato che hai inserito "O1" e "O2"

DECLARE @t TABLE (ID int, IndiceRiga int, OreSuBanco int)
INSERT INTO @t
SELECT
ID
, (SELECT COUNT(*)
FROM dbo.OreLavoro O2
WHERE O2.ID <= O1.ID) as IndiceRiga
, O1.OreSuBanco
FROM
dbo.OreLavoro O1
SELECT
O1.ID
, O1.IndiceRiga
, O1.OreSuBanco - ISNULL(O2.OreSuBanco,0)
FROM
@t O1
LEFT JOIN @t O2 ON O1.IndiceRiga = O2.IndiceRiga + 1

Sono una sorta di indicatori di riga? la sintassi per utilizzarli è indicatore.campo? è un O1 non 0(zero)1, vero?

Grazie,
Michela

paovanm Profilo | Junior Member

Sono riuscita + o - ad adattarlo al mio DB (anche se onestamente sono andata a tentativi e non ho capito molto come abbia fatto... rimangono valide le richieste di info che ti avevo scritto nella e-mail precedente).

Ora ho il risultato della mia sottrazione all'interno della variabile Tabella @t in una colonna che io ho chiamato Oreprova. ... vorrei trasferire i risultati nella tabella originale che contiene i dati che sono stati estratti per calcolare le differenze... come posso fare? Se richiamo la tabella @t per recuperare il valore delle differenze mi richiede di dichiarare nuovamente la variabile @t...

Ho provato ad inserire un UPDATE della tabella iniziale (dbo.OreLavoro nel tuo esempio) all'interno dell'istruzione che calcola la differenza ma mi da errore...

Mi puoi dare un suggeriemento?

Grazie, ciao Michela

alx_81 Profilo | Guru

Ciao!
andiamo per step:

>Sono una sorta di indicatori di riga? la sintassi per utilizzarli è indicatore.campo? è un O1 non 0(zero)1, vero?
Sono gli alias della tabella che mi servono per evitare di scrivere una colonna nella forma NomeTabella.colonna, visto che devo fare delle relazioni su campi della stessa tabelle usata più volte e quindi con lo stesso nome..

>Ora ho il risultato della mia sottrazione all'interno della variabile
>Tabella @t in una colonna che io ho chiamato Oreprova. ... vorrei
>trasferire i risultati nella tabella originale che contiene i
>dati che sono stati estratti per calcolare le differenze... come
>posso fare? Se richiamo la tabella @t per recuperare il valore
>delle differenze mi richiede di dichiarare nuovamente la variabile
>@t...
una volta che hai i dati nella tabella @t, basta fare una UPDATE
UPDATE TuaTabella
SET Campo = CampoDellaTabella@T
FROM TuaTabella
JOIN Tabella@T ON CriterioDiJoin (nella tabella @t devi portare anche l'id per realizzare la relazione di update.

>
>Ho provato ad inserire un UPDATE della tabella iniziale (dbo.OreLavoro
>nel tuo esempio) all'interno dell'istruzione che calcola la differenza
>ma mi da errore...
Non puoi farlo. Devi prima riempire la tabella @t, inserire l'id di relazione e le ore e poi eseguire l'update.
>
>Grazie, ciao Michela
di nulla!

Alessandro Alpi | SQL Server MVP

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi
http://italy.mvps.org

paovanm Profilo | Junior Member

E' più o meno quello che stavo provando ma non mi da la possibilità di fare l'UPDATE, mi da l'errore a livello della terz-ultima riga: Server: messaggio 137, livello 15, stato 2, riga 16
Dichiarare la variabile '@t'.

L'adattamento del mio caso al tuo esempio è il seguante (Ho tolto l'ordinamento perchè i miei record devono essere in ordine "per forza" perchè revisioni successive di un det motore):

CREATE TABLE TabellaDiSupp
(
REV int NOT NULL PRIMARY KEY CLUSTERED
, OreSuBanco smallint NOT NULL,
Oreprova int
)
GO

INSERT INTO TabellaDiSupp (Rev, OreSuBanco, Oreprova)
VALUES (1, 0, 0)
INSERT INTO TabellaDiSupp (Rev, OreSuBanco, Oreprova)
VALUES (2, 290, 0)
INSERT INTO TabellaDiSupp (Rev, OreSuBanco, Oreprova)
VALUES (3, 446, 0)
INSERT INTO TabellaDiSupp (Rev, OreSuBanco, Oreprova)
VALUES (4, 641, 0)
INSERT INTO TabellaDiSupp (Rev, OreSuBanco, Oreprova)
VALUES (5, 738, 0)
INSERT INTO TabellaDiSupp (Rev, OreSuBanco, Oreprova)
VALUES (6, 867, 0)
INSERT INTO TabellaDiSupp (Rev, OreSuBanco, Oreprova)
VALUES (7, 1029, 0)
GO
DECLARE @t TABLE (Rev1 int, OreSuBanco int)
INSERT INTO @t
SELECT
Rev1
, OreSuBanco
FROM
TabellaDiSupp
SELECT
O1.Rev1
, O1.OreSuBanco - ISNULL(O2.OreSuBanco,0) AS [Oreprova]
FROM
@t O1
LEFT JOIN @t O2 ON O1.Rev1 = O2.Rev1 + 1
SELECT * FROM TabellaDiSupp
UPDATE TabellaDiSupp
SET Oreprova = @t.Oreprova
FROM TabellaDiSupp
JOIN @T ON Rev = Rev1

Ciao,
Michela

alx_81 Profilo | Guru

La parte che hai rimosso, non è per l'ordinamento, ma per fare in modo che gli id non abbiano "salti". E potrebbe capitare (errore di inserimento, cancellazione, ecc). Quindi ti consiglio di lasciarlo.. Eccoti l'esempio con l'update e la tua tabella TabellaDiSupp.
USE tempdb; GO -- creazione oggetti CREATE TABLE dbo.TabellaDiSupp ( REV int NOT NULL PRIMARY KEY CLUSTERED , OreSuBanco smallint NOT NULL , Oreprova int ) GO INSERT INTO dbo.TabellaDiSupp (REV, OreSuBanco, Oreprova) VALUES (1, 0, 0) INSERT INTO dbo.TabellaDiSupp (REV, OreSuBanco, Oreprova) VALUES (2, 150, 0) INSERT INTO dbo.TabellaDiSupp (REV, OreSuBanco, Oreprova) VALUES (3, 320, 0) INSERT INTO dbo.TabellaDiSupp (REV, OreSuBanco, Oreprova) VALUES (5, 400, 0) INSERT INTO dbo.TabellaDiSupp (REV, OreSuBanco, Oreprova) VALUES (7, 500, 0) GO -- siccome gli id potrebbero non essere in sequenza, genero un contatore DECLARE @t TABLE (ID int, IndiceRiga int, OreSuBanco int) -- VERSIONE per SQL SERVER 2005 - Funzione ROWNUMBER() /********************************************************************* INSERT INTO @t SELECT ID , IndiceRiga = ROW_NUMBER() OVER (ORDER BY ID) , OreSuBanco FROM dbo.OreLavoro **********************************************************************/ -- VERSIONE per SQL SERVER 2000 -- ********************************************************************* INSERT INTO @t SELECT REV , (SELECT COUNT(*) FROM dbo.TabellaDiSupp O2 WHERE O2.REV <= O1.REV) as IndiceRiga , O1.OreSuBanco FROM dbo.TabellaDiSupp O1 -- ********************************************************************** -- ricavo la sottrazione SELECT O1.ID , O1.IndiceRiga , O1.OreSuBanco - ISNULL(O2.OreSuBanco,0) FROM @t O1 LEFT JOIN @t O2 ON O1.IndiceRiga = O2.IndiceRiga + 1 UPDATE T SET OreProva = O1.OreSuBanco - ISNULL(O2.OreSuBanco,0) FROM dbo.TabellaDiSupp T JOIN @t O1 ON O1.ID = T.REV LEFT JOIN @t O2 ON O1.IndiceRiga = (O2.IndiceRiga + 1) SELECT * FROM dbo.TabellaDiSupp GO -- pulizia DROP TABLE dbo.TabellaDiSupp GO

>Ciao,
Ciao!

Alessandro Alpi | SQL Server MVP

http://www.alessandroalpi.net
http://blogs.dotnethell.it/suxstellino
http://mvp.support.microsoft.com/profile/Alessandro.Alpi
http://italy.mvps.org
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