Newsgroup: it.comp.software.database
Titolo: delete complessa con importi da incrociare e varie condizioni

ciao a tutti
Allora io ho il seguente problema e spero mi possiate aiutare
ho una tabella chiamata STORICO cosi costituita:
1 CASO
ID   |   DATA   |  IMPORTO   | SEGNO   |   BLOCCA
1      20/09/04      100         D           NO
1      20/09/04      100         A           NO
in questo caso facendo delete dovrei cancellare solo i due importi DARE
e AVERE che si incrociano quindi il 100 Dare e il 100 Avere dovrei
cancellarli. Naturalmente se avessi 3 record due DARE e un AVERE di 100
non bisogna cancellarli ma devo lasciare all'utente la possibilità di
decidere quale cancellare
2 CASO
ID   |   DATA   |  IMPORTO   | SEGNO   |   BLOCCA    |   Zona
1      20/09/04      100         D           SI           5
1      20/09/04      100         A           NO           5
in questo caso facendo delete non mi deve cancellare nessuno degli
importi uguali perchè c'è un BLOCCA che è SI.
3 caso
 
ID   |   DATA   |  IMPORTO   | SEGNO   |   BLOCCA   |    Zona
1      20/09/04      100         D           SI           5
1      20/09/04      100         A           NO           5
1      20/09/04      100         D           NO           5
non deve cancellare nulla perchè c'è sempre un BLOCCA su SI
possono esserci anche più record con importi uguali ma se almeno uno ha
il blocca sul SI niente deve essere cancellato.
4 CASO
ID   |   DATA   |  IMPORTO   | SEGNO   |   BLOCCA   |  Zona     
1      20/05/04      100         D           NO          5
1      20/09/04      100         A           NO          5
1      20/09/04      100         D           NO          5
non deve cancellare nulla perchè ho un record che ha una data oltre i 3
mesi...basta avere un record solo che abbia data antecedente i 3 mesi a
quelli successivi.
ALLORA RIEPILOGANDO posso solo cancellare gli importi UGUALI con diverso
SEGNO che hanno il blocca sul NO e che hanno una data non distante i 3
mesi, naturalmente i RECORD uguali con segno diverso devono essere PARI
quindi 2,4,6
esempio
ID   |   DATA   |  IMPORTO   | SEGNO   |   BLOCCA   |   Zona    
1      20/06/04      100         D           NO          5
1      20/09/04      100         A           NO          5
esempio
ID   |   DATA   |  IMPORTO   | SEGNO   |   BLOCCA   |   Zona 
1      20/06/04      100         D           NO           5
1      20/09/04      100         A           NO           5
1      25/06/04      100         D           NO           5
1      20/09/04      100         A           NO           5
in questo caso si possono cancellare
in questo caso NOOOOOO anche se rientrano nei tre mesi e il blocca e su
NO
1      20/09/04      100         A           NO
1      25/06/04      100         D           NO
1      20/09/04      100         A           NO
io per l'incrocio degli importi uguali avevo fatto cosi, in access
naturalmente:
SELECT *
FROM Storico
WHERE (SELECT Round(SUM(IIF(Segno='D',1,-1)*Importo),2) AS Saldo FROM
Storico AS St2 Where St2.Importo = Storico.Importo AND St2.ID=Storico.ID
and storico.Zona='5')=0;
mi aiutate??
 
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG


Uhm non sono un esperto di mysql ma.... in tutti e tre i casi....... ID è 
sempre 1, non si incrementa mai??? :-)
Cooper.
-- 
[web:]  
http://www.blueware.it
 (aggiornato!)
[icq:]  146 781 935
[msn:] 
coo...@blueware.it
 

 
Mi sa tanto di bug da "copia e incolla"... ;)
M.

è un ID numerico legato ad un'altra tabella dove
c'è un ID contatore


Nessun BUG!!!


mi aiutate??
Francamente, si ha la "vaga" impressione che si sia commessa qualche
leggerezza nell'analisi del sistema e nella conseguente progettazione del
database (tra le altre cose, non si capisce quale sia, e se ci sia, la
chiave).
Io non ho la pretesa di aiutarti, che già ho abbastanza difficoltà con i
miei incubi personali, senza cercare di entrare in quelli degli altri.
Per selezionare gli importi uguali, però, a me verrebbe più naturale fare
qualcosa come:
   SELECT ID, IMPORTO,
   Sum(IIf(Segno='D',1,-1)*Importo) AS Saldo
   FROM Storico
   GROUP BY ID, IMPORTO
   HAVING Sum(IIf(Segno='D',1,-1)*Importo)=0;
Per tener conto delle altre condizioni, si potrebbe pensare di definire (se
il sistema lo consente) una funzione utente di "somma" sui campi BLOCCA e
DATA (che restituisca "0" quando nessun BLOCCA è "SI" e la differenza fra
data minima e data massima è inferiore a 3 mesi).
Io comunque risolverei il problema complesso in più passaggi semplici,
piuttosto che cercare un'unica espressione filosofale che mette a posto
tutto. Una volta selezionate (con la select sopra) le registrazioni
(identificate dalla coppia ID, IMPORTO) che "potrebbero" essere cancellate,
si può procedere sequenzialmente, controllando che siano soddisfatte tutte
le altre condizioni, una per una, e quindi cancellare quello che si può.
Per ogni ID, IMPORTO di interesse (siano per esempio: 1, 100), si potrebbe
costruire una select:
   SELECT ID, IMPORTO, BLOCCA
   FROM Storico
   WHERE (ID=1 AND IMPORTO=100 AND BLOCCA="SI");
Se non è vuota, si passa alla coppia ID, IMPORTO successiva; se è vuota, si
controlla la condizione sulla data.
Ciao.

bč si tratta di una tabella correlata ad un altra attraverso un ID
non era necessario in questo caso presentare anche l'altra tabella che 
oltre al totale degli importi dei singoli record dare e avere..
presenta un ID Primario.
Ho cercato di sintetizzare il piů possibile il concetto non č facile
Sono d'accordo con te GIovanni sul fatto di creare forse qualche select
in piů
perň si tratta di migliaia di record di importo diverso e con moltissimi
ID
SELECT ID, IMPORTO,
   Sum(IIf(Segno='D',1,-1)*Importo) AS Saldo
   FROM Storico
   GROUP BY ID, IMPORTO
   HAVING Sum(IIf(Segno='D',1,-1)*Importo)=0;
questa select va bene ma mi evidenzia solo un importo Dare o Avere che
sia
mentre mi deve evidenziare tutti e due gli importi Dare e Avere che
sono uguali..


sono uguali..
Evidenziare tutto è come non evidenziare nulla: hai già la tabella
originale in cui sono contenuti tutti i dati. L'idea è quella di dividere
il compito complesso in più compiti semplici successivi: prima trovi le
coppie (ID, IMPORTO) che POTREBBERO dare zero (e se danno zero,
forzatamente sono in coppie pari Dare e Avere), e poi, su queste, fai i
successivi controlli.
Altrimenti, tanto vale che ordini la tabella (su ID, IMPORTO e altro che ti
sembrasse opportuno), e fai tutto sequenzialmente, leggendo un record alla
volta.
Comunque, ripeto, l'incubo è tuo, non ho la pretesa di conoscere il modo
migliore per uscirne. Posso solo dirti che cosa probabilmente farei io,
nelle medesime circostanze.
Ciao.

è LOGICO CHE QUESTA TABELLA HA UN ID CONTATORE MA NON L'HO SCRITTO
PER EVITARE DI PERDERE TEMPO....BASTAVA UN Pò DI FANTASIA PER ARRIVARCI.
NON SONO UN GRANDE CONOSCITORE DI SQL PERò 
SE TI DICO CHE L'ID è UN ID NUMERICO SI PRESUME CHE CI SIA ANCHE UNO 
CONTATORE DATO CHE ALCUNI DATI SONO UGUALI. CHE DICI???
 
 SELECT ID, IMPORTO,
    Sum(IIf(Segno='D',1,-1)*Importo) AS Saldo
    FROM Storico
    GROUP BY ID, IMPORTO
    HAVING Sum(IIf(Segno='D',1,-1)*Importo)=0;
 
 questa select va bene ma mi evidenzia solo un importo Dare o Avere che
 sia
 
 Certo che sì, proprio questo era lo scopo: evidenzia i gruppi ID,
IMPORTO
 che, in assenza di ulteriori medievali guazzabugli, darebbero somma
zero.
 SUCCESSIVAMENTE, all'interno di questo insieme di gruppi, controli se i
 record corrispondenti soddisfano le altre regole.
NO A ME SERVE CHE MI SI EVIDENZIANO LE COPPIE PERCHè DEVO FARE UNA
DELETE
DI TUTTE LE COPPIE UGUALI ...
TESTANDO LA TUA QUERY MI VIENE SELEZIONATO SOLO UN IMPORTO 
INVECE DEI DUE IMPORTI UGUALI MA DI DIVERSO SEGNO
 Evidenziare tutto è come non evidenziare nulla: hai già la tabella
 originale in cui sono contenuti tutti i dati. L'idea è quella di
dividere
 il compito complesso in più compiti semplici successivi: prima trovi le
 coppie (ID, IMPORTO) che POTREBBERO dare zero (e se danno zero,
 forzatamente sono in coppie pari Dare e Avere), e poi, su queste, fai i
 successivi controlli.
MI SEMBRA GIUSTO!!! 
L'ANALISI L'AVEVO FATTA ANCHE IO....
MA A ME SERVE UNA SOLUZIONE DAL PUNTO DI VISTA DEL CODICE SQL SINTETICA
SE è POSSIBILE..
L'ANALISI E QUELLO CHE DEVO FARE IN TESTA GIà C'è.
 
 Altrimenti, tanto vale che ordini la tabella (su ID, IMPORTO e altro
che ti
 sembrasse opportuno), e fai tutto sequenzialmente, leggendo un record
alla
 volta.
 
SEQUENZIALMENTE è UN'AMMAZZATA SONO PIù DI 6 MILA RECORD
CHE ME LI LEGGO UNO PER UNO SEQUENZIALMENTE E QUANDO AFFITTO|!!!
 Comunque, ripeto, l'incubo è tuo, non ho la pretesa di conoscere il
modo
 migliore per uscirne. Posso solo dirti che cosa probabilmente farei io,
 nelle medesime circostanze.
 
LO SO CHE L'INCUBO è MIO E NON HO PRETESE DA NESSUNO HO SOLO 
CHIESTO AIUTO PUNTO..
 
 Ciao.


  Ciao.
Ciao

 ha scritto nel messaggio
news:MkV3d.472$H11....@twister1.libero.it...

Già... e poi perché urla???

non avevo intenzione di urlare e mi scuso
inconsciamente ho scritto maiuscolo solo per distinguere le mie
risposte..
No non era una risposta nervosa ho solo chiesto aiuto
in sql dato che non lo conosco così abbastanza..
però se espongo le mie difficoltà e qualcuno mi risponde facendomi
un'analisi del problema (cosa che già sapevo e che già avevo fatto io)
teorica e non pratica
e dicendomi che è un mio incubo ....
a chi non girerebbero????
Allora non serve scrivere e chiedere aiuto..


 
Infatti i newsgroup non sono degli helpdesk ai quali appellarsi per 
risolvere i propri problemi. Sono luoghi ove si discute di un 
particolare argomento. Si cerca di dare una mano quando si può, ma non 
si può pretendere che qualcuno abbia la bacchetta magica e che dia la 
risposta che si cerca.
M.

Non ho mai considerato i newsgroup degli help desk, anche perchč sono un
assiduo
frequentatore di vari newsgroup e quando posso cerco di dare una mano
sugli argomenti che piů conosco..
perň dň una mano quando conosco bene l'argomento e quando sň dare 
una risposta e anche spiegare il codice da fare...
Altrimenti non rispondo oppure non intervengo solo per il gusto di
intervenire
Fatto č che non si aiuta certo una persona dicendo č il tuo incubo
sono fatti tuoi..
Credo non serva..o sbaglio?
F.


CHIESTO AIUTO PUNTO..
E IO SOLO TI HO DATO L'AIUTO CHE CHIEDEVI PUNTO. E SE NON LO VUOI PERCHE'
L'HAI CHIESTO PUNTO, PUNTO E VIRGOLA, DUE PUNTI?
Ciao.

sono fatti tuoi..
E a questo punto, che altro potrei fare? Ti ho dato una soluzione, mi dici
"no, voglio fare tutto in una query". "Ma tutto in una query", ti dico "non
si fa". "Sì, ma io voglio fare tutto in una query". Vai, allora, e fai.
Non è lecito anche per me chiederti "allora perché chiedi aiuto, se poi non
ti sta bene quello che ti si dice?".
Ciao.

Ok
Ora ho capito...il discorso di prima
perň anche tu adesso sei stato molto piů dettagliato e mi hai descritto
perfettamente quello che volevi intendere...rispetto a prima
Scusami per la polemica e per i fraintendimenti..
Grazie per la dritta e soprattutto 
GRAZIE MILLE per il tempo che mi hai dedicato..
Nessun rancore???
spero di no!!!


Ok
Ora ho capito...il discorso di prima
perň anche tu adesso sei stato molto piů dettagliato e mi hai descritto
perfettamente quello che volevi intendere...rispetto a prima
Scusami per la polemica e per i fraintendimenti..
Grazie per la dritta e soprattutto 
GRAZIE MILLE per il tempo che mi hai dedicato..
Nessun rancore???
spero di no!!!


Ok
Ora ho capito...il discorso di prima
perň anche tu adesso sei stato molto piů dettagliato e mi hai descritto
perfettamente quello che volevi intendere...rispetto a prima
Scusami per la polemica e per i fraintendimenti..
Grazie per la dritta e soprattutto 
GRAZIE MILLE per il tempo che mi hai dedicato..
Nessun rancore???
spero di no!!!


spero di no!!!
Per le date, sempre nella stessa ottica di procedere per passi successivi
(e posto che abbia compreso bene la condizione), io costruirei una query
Intervalli_date del tipo:
    SELECT ID, IMPORTO, Min(DATA) AS Min, Max(DATA) AS Max
    FROM Storico
    GROUP BY ID, IMPORTO;
Dopo di che, dipende da che cosa intendi per "distante 3 mesi"; se può
equivalere a "meno di 90 giorni" si può fare:
    SELECT ID, IMPORTO, [Max]-[Min] AS Distanza
    FROM Intervalli_date
    WHERE (([Max]-[Min])<90);
Quindi, se "Blocca" è la query:
    SELECT ID, IMPORTO, BLOCCA
    FROM Storico
    WHERE (((BLOCCA)="SI"));
e "zeri" è la query precedente:
    SELECT ID, IMPORTO,
    Sum(IIf(Segno='D',1,-1)*Importo) AS Saldo
    FROM Storico
    GROUP BY ID, IMPORTO
    HAVING Sum(IIf(Segno='D',1,-1)*Importo)=0; 
Potrebbe pure essere, forse magari chissà, che la query:
SELECT zeri.ID, zeri.IMPORTO
FROM (zeri INNER JOIN Distanze ON (zeri.IMPORTO = Distanze.IMPORTO)
                               AND (zeri.ID = Distanze.ID))
           LEFT JOIN Blocca ON (zeri.IMPORTO = Blocca.IMPORTO)
                            AND (zeri.ID = Blocca.ID)
WHERE (((Blocca.ID) Is Null));
(magari si fa meglio, ma in dialetto Access funziona) tiri fuori tutte e
sole le coppie (ID, IMPORTO) di cui si possono cancellare tutti i record.
Io però a questo punto mi sono abbastanza perso da non garantire più nulla
e, anche, non sono sicuro di sapere scrivere una query di delete che
cancelli tutto in un botto.
Ciao.

 WHERE (((Blocca.ID) Is Null));
"Distanze" sarebbe la query:
    SELECT ID, IMPORTO, [Max]-[Min] AS Distanza
    FROM Intervalli_date
    WHERE (([Max]-[Min])<90);
Il trucchetto di fare un LEFT JOIN, e poi scegliere la condizione Is Null,
come detto, in dialetto Access funziona, ed č un sistema per trovare i
record di una tabella che NON sono in un'altra. Non ho la pretesa che sia
l'unico modo, né il migliore, e ancor meno il piů pulito, né che funzioni
ovunque.
Ciao.

grazie ora provo!!!!!
