SQL: filtro su una combinazione di due valori di colonna
Domanda
Ho una tabella saldi
con le seguenti colonne:
bank | account | date | amount
Ho anche una tabella account
che ha bank
e account
come chiave primaria composita.
Voglio fare una query come il seguente pseudocodice:
select date, sum(amount) as amount from balances where
bank and account in (list of bank and account pairs) group by date
L'elenco delle coppie di conti bancari è fornito dal cliente. Come faccio a fare questo? Creare una tabella temporanea e partecipare su di essa?
Sto usando Sybase
Soluzione
Se nella tua app sono note coppie di conti bancari scrivi semplicemente:
(bank = 1 AND account = 2) OR (bank = 3 AND account = 4) OR ...
Se l'elenco delle coppie di conti bancari è una sottoquery, scrivere qualcosa del genere:
SELECT * FROM balances b LEFT JOIN bank_account_pairs p ON ...
WHERE b.bank = p.bank AND b.account = p.account AND ...
Altri suggerimenti
Potrebbe essere utile avere qualche informazione in più.
Se hai dei criteri che guidano il tuo particolare elenco di entità bancarie e di conto, dovresti aderire a queste tabelle.
Hai una tabella Bank e una tabella Account, vero?
Supponendo di avere le informazioni nella tabella dei conti che restringono i conti specifici a cui si desidera fare riferimento, ad esempio supponiamo che la tua tabella dei conti abbia un campo IsActive char (1) NOT NULL e desideri i saldi per i conti inattivi che vorresti scrivere qualcosa del genere:
SELECT date, sum( amount ) AS amount
FROM Balances b
INNER JOIN Accounts a
ON b.Bank = a.Bank AND b.Account = a.Account
WHERE a.IsActive = 'N'
Dal punto di vista del design, probabilmente avresti dovuto creare una chiave artificiale per rimuovere la replica di dati non identificativi tra le tabelle. Questo ti darebbe qualcosa del genere:
CREATE TABLE Accounts (
AccountId int identity(1,1) NOT NULL,
Bank nvarchar(15) NOT NULL,
Account nvarchar(15) NOT NULL
)
CREATE TABLE Balances (
AccountId int,
Date datetime,
Amount money
)
Ciò consente di modificare gli errori nei campi Banca o Conto senza dover mettere in cascata queste modifiche alla tabella Saldi nonché una query leggermente più semplice.
SELECT date, sum( amount ) AS amount
FROM Balances b
INNER JOIN Accounts a
ON b.AccountId = a.AccountId
WHERE a.IsActive = 'N'
Un join interno imporrebbe la combinazione banca + conto, ma è necessario fare attenzione a recuperare più righe del previsto, soprattutto quando si effettuano somme.
Qualcosa di simile al seguente potrebbe funzionare, anche se dipenderà se è supportato in Sybase
select b.date, sum(b.amount) as amount
from balances as b
where exists (select 1 from backaccounts as ba where ba.bank = b.bank and ba.account = b.account)
group by b.date
Se non volessi creare una tabella temporanea, una soluzione sarebbe simile a questa:
select bank, account, sum(amount)
from balances,
(select 'XXX' as bank, 13232 as account
union all
select 'YYY' as bank, 138232 as account
union all
select 'ZZZ' as bank, 183823 as account) banks
where balances.bank = banks.bank
and balances.account = banks.account
Se la tua app è in grado di gestirla, l'opzione migliore è probabilmente questa:
select bank, account, sum(amount)
from balances
where (bank = 'XXX' and account = 123i832)
or (bank = 'YYY' and account = 28323)
or (bank = 'ZZZ' and account = 2839283)