Search  
Friday, May 25, 2012 ..:: Forum ::.. Register  Login
 Forum Minimize
Pentru a putea posta mesaje trebuie să vă înregistraţi.
Notă: Mesajele cu conţinut jignitor sau ilegal (inclusiv cereri de soft piratat) nu sunt acceptate şi vor fi şterse imediat .

Pentru a primi raspunsuri rapide si corecte, scrieti in mesaj ce intentionati sa faceti, ce mesaj de eroare primiti, in ce context si in urma caror actiuni. De asemenea, mentionati versiunea de FoxPro in care lucrati!
Dacă nu specificați versiunea, se consideră VFP 9.0 SP2.

SearchForum Home
  Visual FoxPro  Cod, sintaxa si comenzi  AJUTOR URGENT '...
 AJUTOR URGENT 'SELECT...GROUP BY'
 
 5/15/2011 6:19:32 PM
User is offlineSCHRECK
158 posts
5th


AJUTOR URGENT 'SELECT...GROUP BY'
 (N/A)
Am de rezolvat o problema urgenta. Voi explica prin exemplu ce am si se vreaua sa obtin
Am doua fisiere
PERSONAL.DBF care arata in felul urmator

CNP NUME CNP C(13)
11 POP IOAN
22 MOIS MIA

RATE.DBF

CNP AVANS RATA CNP C(13)
11 250 50
11 0 50
22 300 70
22 0 70
22 0 70

Deci prima inregistrare pt.un cnp nou contine avansul restul 0, iar campul rata contine aceasi valoare
Trebuie sa culeg datele din cele 2 fisiere si sa obtin un fisier care sa contina

NUME AVANS RATA
POP IOAN 250 50
MOIS MIA 300 70

In VFP versiunea 6 am rezolvat problema cu comanda
SELECT p.nume,SUM(r.avans) AS avans,r.rata FROM personal P,rate R WHERE ALLTRIM(P.CNP)==ALLTRIM(R.CNP) GROUP BY nume ORDER BY nume INTO TABLE fisier
Am obtinut ceea-ce am vrut

Folosind aceasi comanda in VFP9 SP2 primesc mesajul de eroare

SQL GROUP BY: clause is missing or invalid

Eroarea dispare daca scriu GROUP BY nume,avans,rata in schimb fiecare nume apare de 2 ori
Nu inteleg de ce in VFP6 functioneaza in si in VFP9 nu

Va rog sa-mi spuneti cum trebuie scris in VFP9 sa functioneze si de ce clauza GROUP BY se comporta diferit in cele 2 versiuni


 5/15/2011 7:08:16 PM
User is offlineDaniel Buduru
2335 posts
1st




Re: AJUTOR URGENT 'SELECT...GROUP BY'
 (N/A)
Incepand cu VFP8, impementarea SQL din vfp a fost adusa mai aproape de standardul ANSI.
Vezi comanda SET ENGINE BEHAVIOR.
Daca vrei sa folosesti acelasi select (nerecomandat), pune comanda SET ENGINE BEHAVIOR 70 undeva inainte de select.

Comanda pe o recomand este urmatoarea:

SELECT p.cnp, p.nume, s.avans, s.rata FROM personal p ;
inner join  (SELECT cnp, SUM(avans) as avans, rata FROM rate GROUP BY cnp, rata) s ;
ON p.cnp=s.cnp ORDER BY nume
 


Daniel Buduru
 5/16/2011 11:05:18 PM
User is offlineSCHRECK
158 posts
5th


Re: AJUTOR URGENT 'SELECT...GROUP BY'
 (N/A)
Asa este functioneaza, desi sintaxa comenzii SELECT camp1,camp2......GROUP BY camp1,camp2.......
cateodata incomodeaza, ne adaptam
Multumesc mult pentru raspuns
 5/17/2011 11:06:12 AM
User is offlineGrigore Dolghin
3590 posts
www.class-software.eu
1st






Re: AJUTOR URGENT 'SELECT...GROUP BY'
 (N/A) Modified By Grigore Dolghin  on 5/17/2011 11:06:43 AM)

 SCHRECK wrote
Am de rezolvat o problema urgenta. Voi explica prin exemplu ce am si se vreaua sa obtin
Am doua fisiere
PERSONAL.DBF care arata in felul urmator

CNP NUME CNP C(13)
11 POP IOAN
22 MOIS MIA

RATE.DBF

CNP AVANS RATA CNP C(13)
11 250 50
11 0 50
22 300 70
22 0 70
22 0 70

Deci prima inregistrare pt.un cnp nou contine avansul restul 0, iar campul rata contine aceasi valoare
Trebuie sa culeg datele din cele 2 fisiere si sa obtin un fisier care sa contina

NUME AVANS RATA
POP IOAN 250 50
MOIS MIA 300 70

In VFP versiunea 6 am rezolvat problema cu comanda
SELECT p.nume,SUM(r.avans) AS avans,r.rata FROM personal P,rate R WHERE ALLTRIM(P.CNP)==ALLTRIM(R.CNP) GROUP BY nume ORDER BY nume INTO TABLE fisier
Am obtinut ceea-ce am vrut

Folosind aceasi comanda in VFP9 SP2 primesc mesajul de eroare

SQL GROUP BY: clause is missing or invalid

Eroarea dispare daca scriu GROUP BY nume,avans,rata in schimb fiecare nume apare de 2 ori
Nu inteleg de ce in VFP6 functioneaza in si in VFP9 nu

Va rog sa-mi spuneti cum trebuie scris in VFP9 sa functioneze si de ce clauza GROUP BY se comporta diferit in cele 2 versiuni

Am mai scris explicatia de cateva ori, da' mi-e lene sa caut. :) Cazul tau este particular - ai aceeasi valoare in campul "rata". Engine-ul SQL n-are de unde sa stie asta. Daca nu specifici campul ala in Group By, VFP6 pune la intamplare una din valori. (in realitate, nu chiar la intamplare, ci pe prima in ordine fizica). Pentru ca ai aceeasi valoare, nu te afecteaza, dar daca ai avea valori diferite n-ai vrea ca VFP sa decida in locul tau ce valoare apare acolo.

Asta era o problema. Serios. Nici un server SQL n-o sa accepte o astfel de sintaxa. Si daca vei vrea vreodata sa portezi aplicatia ta pe un server SQL o sa-ti crape toate SELECT-urile de genul asta. In VFP9 problema a fost eliminata (era bad design anyway) dar au introdus clauza SET ENGINE BEHAVIOR pentru compatibilitate, ca deh, nu toata lumea are chef sa corecteze SQL-urile alea.

O sa dau un exemplu din care se vede ca lipsa obligativitatii clauzei Group By este nashpa. Sa zicem ca ai o tabela de facturi cu urmatoarea structura:

Id      IdClient    NrFactura     DataFactura   ValoareTotala

1            1             0001          15.05.2011        100
2            1             0002          16.05.2011        150
3            2             0003          01.05.2011          75
4            2             0004          03.05.2011        125

Daca executi urmatorul SELECT:

Select IdClient, NrFactura, DataFactura, Sum(ValoareTotala) From Facturi Group By IdClient, VFP6 o sa-ti intoarca un rezultat de genul:

1    0001   15.05.2011     250
2    0003   01.05.2011     200

Acum uite-te la rezultat si intreaba-te: exista vreo factura cu numarul 0001 din data 15.05.2011 cu suma 250? Nu, nu exista. Altfel spus, numarul si data facturi n-au nici o relevanta in context. Sunt niste cifre care nu-ti trebuie. Si asta e cazul fericit. VFP ar putea sa-ti puna numarul facturii citit dintr-o inregistrare si data facturii citita din alta inregistrare si o sa obtii o varza in setul rezultat.

Ori le pui in Group By, ori le dai afara. Daca aveai valori diferite in campul RATA ce faceai?


Grigore Dolghin
Visual FoxPro MVP 2006 - 2010
Class Software
My blog
 5/18/2011 7:00:22 PM
User is offlineSCHRECK
158 posts
5th


Re: AJUTOR URGENT 'SELECT...GROUP BY'
 (N/A)
Sunt de acord cu tine cand proiectezi o baza de date trebuie bine gandita dar in realitate lucrurile stau altcumva.
Un client iti comanda o aplicatie spunand ce vrea. Tu pe baza informatiilor date de el proiectezi baza de date. El introduce vreo mie de
pozitii dupa care iti spune ca mai vrea ceva in plus. Analizand ce vrea ajungi la concluzia ca ar trebui reproiectata toata baza de date din temelii
dar nu poti s-o faci pt.ca clientul spune ca el nu mai introduce inca o data datele el plateste eu sa ma descurc. Uneori prin comenzi fox poti sa creezi
noua baza se date din cele vechi dar cateodata nu. In acest caz trebuie sa recurgi la fel de fel de improvizatii.
 5/18/2011 7:46:52 PM
User is offlineGrigore Dolghin
3590 posts
www.class-software.eu
1st






Re: AJUTOR URGENT 'SELECT...GROUP BY'
 (N/A)

Nu prea sunt de acord cu ce spui. Peste 10 ani, cand o sa ai experienta, nici tu n-o sa mai fii de acord cu ce spui acum. :) Ideea e ca clientul poa'sa zica ce vrea el. Clientul nu e programator, nu e DBA. N-are de unde sa stie. El cunoaste problemele lui - nu-i platesc clientii la timp, i-au cazut masinile de distributie, aia de la leasing il freaca la cap cu ratele, etc etc etc. Sarcina proiectarii bazei de date iti revine tie, nu lui. Daca stai in baza clientului ajungi sa reproiectezi baza aia de date, cu toate problemele aferente (asa cum ai punctat mai sus).

Uite cum as fi facut eu tabela aia a ta: campul avans NU are ce cauta in tabela aia. Sa-ti spun si de ce: avansul este o chestie one-time-only, rata e in fiecare luna. Tu ai reusit sa creezi o coloana in care ai completat un singur rand pentru fiecare angajat, iar restul (daca angajatul are 100 de rate - restul inseamna 99 de randuri) contin zero. Design neglijent, risipa de spatiu, risipa de IO, risipa de procesor la interogari. De ce? pentru ca l-ai ascultat orbeste pe client si nu ai filtrat informatiile de la el prin propriul tau discernamant. Sigur, la inceput (banuiesc ca esti tanar) n-ai de unde sa stii; trebuie sa o iei in freza de cateva ori apoi incet incet iti dai seama ca dupa ureche nu merge. Ma rog, cunosc oameni care au 50 de ani si inca n-au ajuns la concluzia asta, ci continua sa "urecheasca" tot felul de baze de date de doi lei.

Eu as fi facut trei tabele:

Personal.dbf - cu campurile ID, CNP, NUME, PRENUME
Avans.dbf - cu campurile ID, IDPERSONAL, VALOARE, DATA
Rate.dbf - cu campurile ID, IDPERSONAL, RATA, DATA

Problema ta s-ar fi rezolvat cu o instructiune de genul SELECT Personal.Nume, Personal.Prenume, (Select valoare from avans where avans.idpersonal = personal.id) As Avans, sum(rate.rata) From Personal  Left Join rate On personal.id = rate.idpersonal group by personal.id, personal.nume, personal.prenume

(te rog sa remarci subquery-ul din lista de campuri).

Si obtin fix tabela ta, cu group by pe ce-mi trebuie, fara dureri de cap.

Daca ala o sa vrea vreodata suma de rate, un select simplu rezolva problema. Daca vrea suma de avansuri, un select simplu rezolva problema. Daca vrea mai stiu eu ce-i trece prin cap cu campurile de avans si de rata, un select (relativ) simplu rezolva problema.

Si asta pentru ca in designul asta ENTITATILE sunt izolate in tabele proprii (forma a 3-a de normalizare, da' deh, trebuie sa mai si citim, nu merge doar dupa ureche, fratioare). Tu ai amestecat in tabela ta doua lucruri diferite si e normal sa ai dificultati cand vrei sa faci calcule diferite pe fiecare in parte. Si da, tocmai ai ajuns intr-o astfel de situatie.


Grigore Dolghin
Visual FoxPro MVP 2006 - 2010
Class Software
My blog
 5/19/2011 12:23:21 PM
User is offlineGrigore Dolghin
3590 posts
www.class-software.eu
1st






Re: AJUTOR URGENT 'SELECT...GROUP BY'
 (N/A)

Imi permit sa reinnoiesc oferta asta:

http://www.profox.ro/Forum/tabid/55/forumid/1/threadid/34697/scope/posts/Default.aspx


Grigore Dolghin
Visual FoxPro MVP 2006 - 2010
Class Software
My blog
 6/1/2011 12:49:58 AM
User is offlineSCHRECK
158 posts
5th


Re: AJUTOR URGENT 'SELECT...GROUP BY'
 (N/A)
Cu intarziere am sa-ti raspund la sfaturile tale.
Ai dreptate in felul tau dar asta pt. ca eu am schitat sumar problema.
In realitate lucrurile stau mai complicat. Este vorba de asa numite programe la
‘comanda’ in care clientul iti spune cam ce vrea dar pe parcurs modifica multe
lucruri. Deci in concluzie trebuie sa proiectezi o baza de date fara sa stii structura lui finala.
In asemenea situatii eu creez un tabel mare care cuprinde toate datele alagand o cheie
Unica, in cazul de fata CUI/CNP. In cazul in care trebuie sa fac relatii una la mai multe
Mai creez fisiere aditionale cu aceasi cheie unica, dar care se repeta ex .rata cu structura
Cnp…..rata.
Cand se clarifica definitiv situatie, analizez si prin comenzi SQL optimizez si fac mai multe tabele, iar interfata o impart in cadre de pagina.

Tu cum ai proceda cand ai trebui sa proiectezi o aplicatie fara sa stii structura bazalor de date?

Legat de problema doua pt.care mai certat este fisierul cu avans si rate.
Problema este ca directorul vrea neaparat o interfata simpla in care operatorul sa poate vedea totul intr-o singura fereastra ca sa poata opera platile la rate. Sub forma

Data rata Avans Rata Achitat Data Achitarii
01/01/2001 1000 1000 01/01/2011
01/02/2011 0 100 100 05/01/2011
01/03/2011 0 100 20 05/03/2011
01/04/2011 0 100 0



Prin urmare am facut aceata tabela, pt. care m-ai certat, pentru a-l pune intr-un grid.
Situatia nu aste asa treagica, se poate usor ajunge la fisierele propuse de tine, ex pt
Fisierul avans SELECT cnp,avans FROM rata WHERE avans#0 INTO TABLE avans

Tu cum ai fi procedat ?
Referitor la problema propusa de tine m-ar tenta desi nu sunt chiar incepator mai am multe lucruru de invatat, problema este ca ne despart vreo 700 km.
Poate o sa gasim o alta forma de colaborare
 6/1/2011 10:30:27 AM
User is offlineSCHRECK
158 posts
5th


Re: AJUTOR URGENT 'SELECT...GROUP BY'
 (N/A)

TABELUL MAI EXPLICIT

Data rata               Avans                Rata             Achitat                 Data achitarii

01/01/2011            1000                                      1000                     01/01/2011

01/02/2011                                    100                  100                     05/02/2011

01/03/2011                                    100                    20                     05/03/2011

01/04/2011                                    100              

 6/1/2011 5:02:08 PM
User is offlineGrigore Dolghin
3590 posts
www.class-software.eu
1st






Re: AJUTOR URGENT 'SELECT...GROUP BY'
 (N/A)
 SCHRECK wrote
Cu intarziere am sa-ti raspund la sfaturile tale.
Ai dreptate in felul tau dar asta pt. ca eu am schitat sumar problema.
In realitate lucrurile stau mai complicat. Este vorba de asa numite programe la
‘comanda’ in care clientul iti spune cam ce vrea dar pe parcurs modifica multe
lucruri. Deci in concluzie trebuie sa proiectezi o baza de date fara sa stii structura lui finala.
In asemenea situatii eu creez un tabel mare care cuprinde toate datele alagand o cheie
Unica, in cazul de fata CUI/CNP. In cazul in care trebuie sa fac relatii una la mai multe
Mai creez fisiere aditionale cu aceasi cheie unica, dar care se repeta ex .rata cu structura
Cnp…..rata.
Cand se clarifica definitiv situatie, analizez si prin comenzi SQL optimizez si fac mai multe tabele, iar interfata o impart in cadre de pagina.

Tu cum ai proceda cand ai trebui sa proiectezi o aplicatie fara sa stii structura bazalor de date?

Legat de problema doua pt.care mai certat este fisierul cu avans si rate.
Problema este ca directorul vrea neaparat o interfata simpla in care operatorul sa poate vedea totul intr-o singura fereastra ca sa poata opera platile la rate. Sub forma

Data rata Avans Rata Achitat Data Achitarii
01/01/2001 1000 1000 01/01/2011
01/02/2011 0 100 100 05/01/2011
01/03/2011 0 100 20 05/03/2011
01/04/2011 0 100 0



Prin urmare am facut aceata tabela, pt. care m-ai certat, pentru a-l pune intr-un grid.
Situatia nu aste asa treagica, se poate usor ajunge la fisierele propuse de tine, ex pt
Fisierul avans SELECT cnp,avans FROM rata WHERE avans#0 INTO TABLE avans

Tu cum ai fi procedat ?
Referitor la problema propusa de tine m-ar tenta desi nu sunt chiar incepator mai am multe lucruru de invatat, problema este ca ne despart vreo 700 km.
Poate o sa gasim o alta forma de colaborare


Hehehe :) Ma uit la mesajul meu anterior si-mi vine sa rad. Uite ce scrisesem:

--------------------------------
Eu as fi facut trei tabele:

Personal.dbf - cu campurile ID, CNP, NUME, PRENUME
Avans.dbf - cu campurile ID, IDPERSONAL, VALOARE, DATA
Rate.dbf - cu campurile ID, IDPERSONAL, RATA, DATA
--------------------------------

Am pus campul de data fara sa stiu nimic despre aplicatia ta. :) Si cand colo, surpriza, chiar trebuia. Intelegi ideea? O buna parte din amanuntele astea se pot anticipa, chiar daca nu stii nimic despre ele. In fine, revenind la subiect:

Sunt in continuare de parere ca nu procedezi bine si uite argumentul meu: Cand discuti despre o aplicatie cu un client focusul trebuie sa stea pe entitatile din aplicatie. Baza de date vine DUPA ce sunt stabilite entitatile astea. In cazul concret de mai sus, in tabela ta sunt DOUA entitati distincte, care au doua campuri comune (valoare si data), dar sunt distincte pentru ca FUNCTIONEAZA diferit. Avansul este ceva, rata este altceva. Daca le pui in aceeasi tabela e ca si cum ai considera ca avansul este o rata, ceea ce categoric nu este corect.

 SCHRECK wrote

In asemenea situatii eu creez un tabel mare care cuprinde toate datele alagand o cheie Unica, in cazul de fata CUI/CNP.

In pasajul de mai sus ai doua erori de design. #1. NICIODATA sa nu creezi un singur tabel mare, completat ca la x si zero. Never, ever, ever. Izolezi entitatile logice si faci tabele distincte. #2. NICIODATA sa nu folosesti ceva introdus de utilizator pe post de cheie unica, fiindca utilizatorul este om si greseste (unii mai gresesc si intentionat, dar ca sa-ti faca viata grea. Been there, done that). Stii de ce? Fiindca daca angajatul ala pleaca din firma, inregistrarile lui raman din motive istorice, de exemplu. Si peste 6 luni iti vine inapoi si trebuie sa-l bagi la loc in tabela. Si pentru ca ai avut proasta inspiratie sa-i folosesti CNP-ul pe post de cheie primara, houston, we've got a problem. Nu mai poti sa deosebesti inregistrarile vechi de alea noi. Repet, e doar un exemplu. Poate nu ti se aplica, dar asta nu inseamna ca ai facut bine. Cheia primara este INTOTDEAUNA generata si intretinuta de sistem (am obosit sa repet asta, deja. Cred ca am scris-o de cel putin 20 de ori numai aici pe forum).

 SCHRECK wrote

Tu cum ai proceda cand ai trebui sa proiectezi o aplicatie fara sa stii structura bazalor de date?

Cand proiectez aplicatia nu ma intereseaza structura bazelor de date. Aceea este o etapa ulterioara. Prima data se discuta despre business-ul acoperit de aplicatie. Business-ul ala are niste entitati cu care functioneaza. ALEA trebuie puse pe hartie, apoi trebuie descris modul in care interactioneaza entitatile astea intre ele (asa-numitele procese de business). Sa stii ca notiunile astea n-au fost inventate degeaba si nu reprezinta cuvinte mari cu care sa epatezi lumea. Dimpotriva - daca nu le folosesti mai devreme sau mai tarziu o iei in freza; e doar o problema de timp.

In cazul tau concret, probabil ca discutia ar fi trebuit sa fie cam asa

El: "Am pe unii care trebuie sa-mi achite niste rate. Ei platesc un avans, apoi lunar o rata."

Pe hartie apar doua entitati: Avans si Rata lunara

Tu: "Si cand se termina creditul asta omul poa'sa mai ia altul?"
El: "Da" sau "Nu". (eu personal cred ca raspunsul este "da")

Indiferent de raspunsul lui, pe hartie apare a treia entitate: Creditul, care este parintele celor doua entitati de mai devreme.

Tu: "In afara de avans si rate mai e ceva de plata in toata povestea asta?"
El: "Nu"

Ok, te apuci de treaba si faci trei tabele:

Credit.dbf, cu structura: ID, PERSONAL_ID,NUMAR,DATA (creditul ala tre'sa aiba un numar si o data - sunt absolut sigur de chestia asta) Daca n-are, big problem - ca o sa te uiti intr-o lista uriasa de inregistrari si n-o sa stii care si de unde.

Avans.dbf, cu structura ID, CREDIT_ID, SUMA, ACHITAT, DATA

Rate.dbf, cu structura ID, CREDIT_ID, SUMA, ACHITAT, DATA

In fereastra de data entry ai un textbox read-only cu numele angajatului, sub el unul cu valoarea avansului, si dedesubt un grid cu ratele. Valoarea achitata se inregistreaza in grid. Super simplu si ai totul intr-o singura fereastra.

Peste 6 luni vine nebunu' de director si-ti spune "Tre'sa modificam programul - trebuie sa introduca si valoarea reziduala la contract." Scoti frumusel hartia de la prima discutie si mai adaugi o entitate, langa avans: Valoare Reziduala, subordonata creditului.

Faci inca o tabela - Valoare_Reziduala.dbf, cu structura ID, CREDIT_ID, SUMA, ACHITAT, DATA

Vezi diferenta? orice se intampla in viitor, ce-ai facut ramane facut si functional.


Grigore Dolghin
Visual FoxPro MVP 2006 - 2010
Class Software
My blog
  Visual FoxPro  Cod, sintaxa si comenzi  AJUTOR URGENT '...

Search  Forum Home         

 Google Ads Minimize

    

Copyright 2002-2010 Profox   Terms Of Use  Privacy Statement