2012-07-07 16 views
5

tabelle utilizzate:query SQL per selezionare una colonna con espressione di valore non aggregata e funzione di aggregazione

1) v (data d, nome c (25), desc c (50), di addebito n (7), credito n (7))

nome 'v' fa riferimento nella tabella VII

2) vn (data d, nome c (25), di tipo c (25), obal n (7))

nome in 'vn' è una chiave primaria e diversi nomi sono raggruppati per tipo

es: nomi abc, def, ghi appartiene al tipo 'banca', i nomi XYZ, PQR appartiene al tipo 'libro mastro', ...

Ho una query come questa:

Funziona bene ma l'unico problema è, obal è un valore che viene immesso una sola volta per nome nella tabella 'vn' ma con questa query per ogni calcolo di credito-debito nella tabella 'v', l'obal viene aggiunto più volte e visualizzato sotto OpBal. Quando la query viene modificata come di seguito:

SELECT vn.type, vn.obal + SUM(IIF(v.date < sd, v.credit-v.debit, 0)) OpBal, ; 
    SUM(IIF(BETWEEN(v.date, sd, ed), v.credit-v.debit, 0)) CurBal ; 
    FROM v, vn WHERE v.name = vn.name GROUP BY vn.type ; 
    ORDER BY vn.type HAVING OpBal + CurBal != 0 

mostra un messaggio di errore come "La clausola di gruppo manca o non è valida"!

RDBMS utilizzato MS Visual Foxpro 9. sd ed ed sono variabili di tipo data utilizzate allo scopo di query dove sd < ed.

Please help me out ottenere il risultato atteso. Molte grazie.

+0

È necessario raggruppare per nella tabella 'vn' e quindi unire il risultato alla query che si ha. –

+0

@Dems: stavo pensando a cosa sarebbe stato necessario per una query 'GROUP BY vn.type'. Con un 'GROUP BY type, obal', penso che la tua risposta sia soddisfacente. (A proposito, questo è "HAVING" dopo la sintassi valida di "ORDER BY" in Foxpro? Mi fa meravigliare) –

+0

E ho assunto che la chiave primaria di 'vn' è' nome', dalla descrizione. –

risposta

0

ho visto la sintassi SQL per SQL con VFP per la prima volta a pochi minuti fa, quindi questo potrebbe essere pieno di errori, ma come un 'intuizione guessful':

SELECT vn.type, 
     SUM(vn.obal + (SELECT SUM(IIF(v.date < sd, v.credit-v.debit, 0)) 
         FROM v 
         WHERE v.name = vn.name)) OpBal, 
     SUM(SELECT SUM(IIF(BETWEEN(v.date, sd, ed), v.credit-v.debit, 0)) 
      FROM v 
      WHERE v.name = vn.name) CurBal 
FROM vn 
GROUP BY vn.type 
ORDER BY vn.type 
HAVING OpBal + CurBal != 0 

Fondamentalmente, io' Ho appena attivato la selezione da v in subselect per evitare che vn.obal venga ripetuto. Non dovrebbe importare per v che prima ottiene la somma per la persona individuale prima di sommarli tutti insieme.

+0

Imposta, mi spiace! Viene generato un messaggio di errore: 'Nome funzione mancante'. ' – Ganapathy

0

solo alcune cose. VFP 9 ha un'impostazione per NON richiedere il raggruppamento per tutti i non aggregati per la compatibilità con le versioni precedenti e risultati simili come MySQL dove non tutte le colonne devono essere aggregate. Ad esempio interrogare colonne aggiuntive da un record del cliente che non cambiano mai, non importa quanti record si uniscono contro nella sua colonna PK (nome, indirizzo, telefono, qualunque cosa).

SET ENGINEBEHAVIOR 80 

predefinito per VFP 9

SET ENGINEBEHAVIOR 90 

richiede tutti i non-gruppo da colonne di essere aggregati per conformarsi.

Avanti ... sembra che tu abbia colonne molto cattive nei tavoli con cui hai a che fare ... 3 parole riservate in VFP ... "data", "Nome" e "tipo", comunque tu sei ok qualificandoli nella query con il riferimento alias.column.

Il seguente codice di esempio creerà tabelle temporali (cursori) delle strutture che hai descritto nella domanda.Ho anche inserito alcuni dati di esempio e simulato il vostro "SD" (data di inizio) e "ed" (data di scadenza) variabili

CREATE CURSOR vn; 
    (date d, ; 
    name c(25), ; 
    type c(25), ; 
    obal n(7)) 

INSERT INTO vn VALUES (CTOD("5/20/2012"), "person 1", "person type 1", 125) 
INSERT INTO vn VALUES (CTOD("5/20/2012"), "person 2", "another type ", 2155) 

CREATE CURSOR v; 
    (date d, ; 
    name c(25), ; 
    desc c(50), ; 
    debit n(7), ; 
    credit n(7)) 

INSERT INTO V VALUES (CTOD("6/1/2012"), "person 1", "description 1", 10, 32) 
INSERT INTO V VALUES (CTOD("6/2/2012"), "person 1", "desc 2", 235, 123) 
INSERT INTO V VALUES (CTOD("6/3/2012"), "person 1", "desc 3", 22, 4) 
INSERT INTO V VALUES (CTOD("6/4/2012"), "person 1", "desc 4", 53, 36) 
INSERT INTO V VALUES (CTOD("6/5/2012"), "person 1", "desc 5", 31, 3) 
INSERT INTO V VALUES (CTOD("6/1/2012"), "person 2", "another 1", 43, 664) 
INSERT INTO V VALUES (CTOD("6/4/2012"), "person 2", "more desc", 78, 332) 
INSERT INTO V VALUES (CTOD("6/6/2012"), "person 2", "anything", 366, 854) 

sd = CTOD("6/3/2012")  && start date of transactions 
ed = DATE() && current date as the end date... 

Ora, l'interrogazione ... Si sta tentando di ottenere i gruppi in base al tipo, ma il per persona (nome) deve essere pre-aggregato su una base per persona PRIMA. Ora, sembra che tu stia cercando di ottenere un saldo di apertura totale delle transazioni prima della data di inizio (sd) come base in un determinato momento, quindi osservando l'attività ENTRO la data di inizio/fine in questione. Fai prima questo, ma non fare i conti con l'aggiunta nella colonna "obal" dalla tabella "vn". Dal momento che ha bisogno di aggregati di non-gruppo per colonne, vorrei semplicemente usare "MAX()" della colonna. Poiché è basato su un PK (nome), finirai con qualunque cosa fosse, ma con i totali accumulati delle transazioni, ma hai tutti i tuoi dati riassunti in una singola riga tramite ...

select; 
     vn.name,; 
     vn.type,; 
     MAX(vn.obal) as BalByNameOnly,; 
     SUM(IIF(v.date < sd, v.credit-v.debit, 000000.00)) OpBal, ; 
     SUM(IIF(BETWEEN(v.date, sd, ed), v.credit - v.debit, 000000.00)) CurBal ; 
    FROM ; 
     v,; 
     vn ; 
    WHERE ; 
     v.name = vn.name; 
    GROUP BY ; 
     vn.Name,; 
     vn.Type; 
    INTO ; 
     CURSOR C_JustByName READWRITE 

Con questo risultato (dal mio dati di esempio) sarebbe simile ...

Name  Type   BalByNameOnly OpBal CurBal 
person 1 person type 1  125   -90  -63 
person 2 another type  2155   621  742 

vostro aggregato finale per ottenere per tipo, si può solo interrogare il risultato di cui sopra "cursore" (C_JustByName) e usarlo per raggruppare per tipo, per avere, ecc. qualcosa come

SELECT ; 
     JBN.type, ; 
     JBN.BalByNameOnly - JBN.OpBal as OpBal,; 
     JBN.CurBal ; 
    FROM ; 
     C_JustByName JBN ; 
    GROUP BY ; 
     vn.type ; 
    ORDER BY ; 
     vn.type ; 
    HAVING ; 
     OpBal + CurBal != 0; 
    INTO ; 
     CURSOR C_Final 

Ora, sto semplicemente semplificando quanto sopra perché non so cosa stai cercando come la data all'interno del tuo "VN" (sembra essere come una tabella dei clienti) con una data che non è chiara il suo scopo e il suo colonna oBal rispetto alla tabella delle transazioni.

La cosa bella di VFP è che è possibile eseguire una query in un cursore temporaneo senza creare una tabella permanente e utilizzare l'IT come base per qualsiasi query successiva ... Aiuta la leggibilità di non dover annidare la query all'interno della query query interna. Permette anche di vedere i risultati di ogni livello e sapere che stai ottenendo le risposte che stai ASPETTANDO prima di passare alla fase successiva della query ...

Speriamo che questo ti aiuti nella direzione di ciò che stai cercando di risolvere .

Problemi correlati