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  Distribuire o s...
 Distribuire o suma in bani mai multor facturi
 
 1/25/2012 7:35:39 AM
User is offlineviciuascuns
4 posts


Distribuire o suma in bani mai multor facturi
 (N/A) Modified By viciuascuns  on 1/25/2012 8:44:06 AM)
Salutari

Este primul meu mesaj aici.

Sa presupunem ca avem o suma de 0,70 lei. Cum se pot distribui acesti bani pe mai multe facturi, in campul suma, in mod egal (sa spunem 6 inregistrari)? In cazul in care ramane un rest, acesta trebuie distribuit in continuare facturii urmatoare (un fel de bucla). Tabela are un index si nu se poate rezolva cu parcurgerea cu skip +1 a inregistrarilor.

facturi (id,data,suma)

Ma poate ajuta cineva?
 1/25/2012 8:53:08 AM
User is offlineDaniel Buduru
2335 posts
1st




Re: Distribuire o suma in bani mai multor facturi
 (N/A)
Bine ai venit pe forum.

Comenzile Scan, Skip, Replace parcurg tabela in ordinea indexului, daca exista un index activ.
Daca indexul nu corespunde cu ordinea in care sunt facturile, dezactivezi indexul cu comanda Set order to
Poti face inlocuirea fie prin parcurgerea secventiala a tabelei, cu scan sau skip, fie printr-o comanda globala :

Replace next 6 camp with valoare
Skip
Replace camp with valoare

Poti face inlocuirea si cu o comanda Update SQL, comanda pe care o poti folosi pe orice baza de date sql.
Trebuie sa gasesti un criteriu comun celor 6 facturi pe care vrei sa le modifici, de exemplu numarul facturii:

Update facturi set suma=suma+x where nrfactura between numarul_primei_facturi and numarul_primei_facturi+5

Sau
Update facturi set suma=suma=x where id in (select top 6 id from facturi where id>=id_al_primei_facturi order by id )
Update facturi set suma=suma+y where id in (select top 1 id from (select top 7 id from facturi where id>=id_al_primei_facturi order by id) cc order by id desc)

Functioneaza daca id este alocat secvential, si nu random.


Daniel Buduru
 1/25/2012 9:23:59 AM
User is offlineviciuascuns
4 posts


Re: Distribuire o suma in bani mai multor facturi
 (N/A)
De fapt, am rezolvat astfel:

      SELECT facturi
      SCAN FOR facturi.tip = 11
   
            cid = facturi.id_om
            USE nom!om_selectiv IN 0 ALIAS om_selectiv
           
              SELECT facturi
            original = facturi.ramas
            diferenta = facturi.ramas

            IF diferenta < 0
                unitate = -0.01
            ELSE
                unitate = 0.01           
            endif               

            SELECT om_selectiv
            DO WHILE diferenta <> 0.00
                SCAN FOR om_selectiv.semnal = 1
                    IF (diferenta<>0.00)
                                diferenta = diferenta - unitate
                            replace om_selectiv.valoare_factura WITH om_selectiv.valoare_factura + unitate
                    ENDIF
                    SELECT om_selectiv
                endscan       
            ENDDO
        
          SELECT facturi
      ENDSCAN
 1/25/2012 10:22:56 AM
User is offlineDaniel Buduru
2335 posts
1st




Re: Distribuire o suma in bani mai multor facturi
 (N/A)
 viciuascuns wrote
De fapt, am rezolvat astfel:

      SELECT facturi
      SCAN FOR facturi.tip = 11
   
            cid = facturi.id_om
            USE nom!om_selectiv IN 0 ALIAS om_selectiv
           
              SELECT facturi
            original = facturi.ramas
            diferenta = facturi.ramas

            IF diferenta < 0
                unitate = -0.01
            ELSE
                unitate = 0.01           
            endif               

            SELECT om_selectiv
            DO WHILE diferenta <> 0.00
                SCAN FOR om_selectiv.semnal = 1
                    IF (diferenta<>0.00)
                                diferenta = diferenta - unitate
                            replace om_selectiv.valoare_factura WITH om_selectiv.valoare_factura + unitate
                    ENDIF
                    SELECT om_selectiv
                endscan       
            ENDDO
        
          SELECT facturi
      ENDSCAN


1. Nu e indicat sa deschizi o tabela intr-o bucla si sa o lasi deschisa.
    Fie deschizi om_selectiv inaintea primului scan, fie inchizi tabela inainte de endscan.
    Poti folosi si o astfel de comanda:
    Use om_selectiv in (select('om_selectiv'))
    care va redeschide tabela in acceasi zona.
    Deschiderea unei tabela este o operatie consumatoare de resurse, si ar trebui redusa la strictul necesar.

2. Sintaxa corecta a comenzii replace este urmatoarea:
    Replace camp With valoare IN ALIAS

3. Nu vad o legatura intre tabela facturi si tabela om_selectiv.
Desi extragi id_om din facturi, nu vad sa il folosesti cumva mai departe, ci scanezi de fiecare data intreaga tabela om_selectiv. 
Este corect asa? Nu ai cumva id_om in om_selectiv, in functie de care ar trebui sa faci distribuirea sumei?




Daniel Buduru
 1/25/2012 11:29:45 AM
User is offlineviciuascuns
4 posts


Re: Distribuire o suma in bani mai multor facturi
 (N/A) Modified By viciuascuns  on 1/25/2012 12:33:02 PM)
Om_selectiv este de fapt un view si are ca parametru CID
 1/25/2012 12:19:03 PM
User is offlineDaniel Buduru
2335 posts
1st




Re: Distribuire o suma in bani mai multor facturi
 (N/A)
Inteleg ca acel cid este conditia de filtru a view-ului parametrizat, si de aceea redeschzi view-ul de fiecare data.
E suficient sa deschizi view-ul inainte de scan facturi, apoi sa faci un requery('om_selectiv') dupa alocarea noii valori a lui cid.

Ar trebui sa actualizezi si valoarea ramasa in facturi dupa actualizarea valorii in om_selectiv.

Solutia iterativa pe care ai adoptat-o isi face treaba, dar timpul de executie e proportional cu numarul de inregistrari.
Se poate face si altfel, se poate calcula cota de repartizare si se poate aplica global, prin comenzi sql
Repartizarea restului, cate 0.01/factura, necesita insa, in vfp, o parcurgere secventiala.

Uite un exemplu:

CREATE CURSOR facturi (id_om int, ramas n(10,2))
FOR lni=1 TO 1000
INSERT INTO facturi VALUES (lni, RAND()*100)
next

CREATE CURSOR om_selectiv (id int, id_om int, semnal int, valoare_factura n(10,2))
for lni=1 to 10000
INSERT INTO om_selectiv (id, id_om, semnal) VALUES (lni, RAND()*100, Round(RAND(),0))
next

SELECT ff.id_om, ff.ramas, oms.cnt, FLOOR(ff.ramas*100/oms.cnt)*0.01 as cota, (ff.ramas*100%oms.cnt) as restcota FROM facturi ff INNER JOIN ;
(SELECT id_om, COUNT(*) as cnt FROM om_selectiv  GROUP BY id_om) oms ;
ON  ff.id_om=oms.id_om ;
WHERE ff.ramas<>0 ;
INTO CURSOR crsFact

UPDATE om_selectiv SET valoare_factura=valoare_factura+crsfact.cota from crsfact WHERE om_selectiv.id_om=crsfact.id_om

SELECT crsfact
SCAN ALL FOR restcota<>0
lnrecs=ABS(crsfact.restcota)
UPDATE om_selectiv SET valoare_factura=valoare_factura+0.01 ;
WHERE id in (select top (ABS(crsfact.restcota)) id from om_selectiv WHERE om_selectiv.id_om=crsfact.id_om order by 1)
ENDSCAN

SELECT ff.id_om, ff.ramas, ss.cnt, ss.repartizat, ff.ramas-ss.repartizat as diferenta ;
FROM facturi ff ;
INNER JOIN ;
(select id_om, COUNT(*) as cnt, SUM(valoare_factura) as repartizat FROM om_selectiv GROUP BY id_om) ss ;
ON ff.id_om=ss.id_om


Daniel Buduru
 1/25/2012 12:28:00 PM
User is offlineviciuascuns
4 posts


Re: Distribuire o suma in bani mai multor facturi
 (N/A)
Mersi mult. O sa incerc.
 1/25/2012 4:30:36 PM
User is offlineDaniel Buduru
2335 posts
1st




Re: Distribuire o suma in bani mai multor facturi
 (N/A)
SQL implementat in vfp are o serie de limitari fata de implementarile de pe serverele sql, dar se pot ocoli cumva, cu pretul crearii unor cursoare intermediare.
Am gasit si in vfp o solutie fara parcurgerea secventiala a cursorului.

CREATE CURSOR facturi (id_om int, ramas n(10,2))
FOR lni=1 TO 1000
INSERT INTO facturi VALUES (lni, RAND()*100)
next

CREATE CURSOR om_selectiv (id int, id_om int, semnal int, valoare_factura n(10,2))
for lni=1 to 10000
INSERT INTO om_selectiv (id, id_om, semnal) VALUES (lni, RAND()*100, Round(RAND(),0))
next

SELECT ff.id_om, ff.ramas, oms.cnt, FLOOR(ff.ramas*100/oms.cnt)*0.01 as cota, (ff.ramas*100%oms.cnt) as restcota FROM facturi ff INNER JOIN ;
(SELECT id_om, COUNT(*) as cnt FROM om_selectiv  GROUP BY id_om) oms ;
ON  ff.id_om=oms.id_om ;
WHERE ff.ramas<>0 ;
INTO CURSOR crsFact

SELECT RECNO() as rec, id, id_om FROM (SELECT id, id_om FROM om_selectiv ORDER BY id_om)aa INTO CURSOR crsom

UPDATE om_selectiv SET valoare_factura=valoare_factura+crsfact.cota from crsfact WHERE om_selectiv.id_om=crsfact.id_om

UPDATE om_selectiv SET valoare_factura=valoare_factura+0.01 ;
from ;
(SELECT cf.id_om, cf.cota, cf.restcota, co.id, co.rec, cs.first, cs.first+cf.restcota-1 as last ;
FROM crsfact cf ;
INNER JOIN crsom co ON cf.id_om=co.id_om ;
INNER JOIN (select MIN(rec) as first, id_om FROM crsom GROUP BY id_om) cs ON co.id_om=cs.id_om) ss ;
where om_selectiv.id=ss.id AND ss.rec between ss.first AND ss.last


SELECT ff.id_om, ff.ramas, ss.cnt, ss.repartizat, ff.ramas-ss.repartizat as diferenta ;
FROM facturi ff ;
INNER JOIN ;
(select id_om, COUNT(*) as cnt, SUM(valoare_factura) as repartizat FROM om_selectiv GROUP BY id_om) ss ;
ON ff.id_om=ss.id_om



Daniel Buduru
  Visual FoxPro  Cod, sintaxa si comenzi  Distribuire o s...

Search  Forum Home         

 Google Ads Minimize

    

Copyright 2002-2010 Profox   Terms Of Use  Privacy Statement