2016-06-30 13 views
2

請求書を作成した人がいる請求書テーブルがあります。人は複数のオフィスに所属でき、1人の本店は1人だけですが、同じ人はオフィスごとに複数の役割を持つことができます。SQL Server 2012:複数のテーブル結合から集計グループを取得する方法

declare @person table (personid int) 
declare @office table (officeid int, officename varchar(10)) 
declare @personoffice table (personid int, officeid int, mainoffice bit, personrole varchar(10)) 
declare @invoice table (personid int) 

insert into @person values (1), (2), (3), (4) 
insert into @office values (1, 'office1'), (2, 'office2'), (3, 'office3'), (4, 'office4') 
insert into @personoffice values (1, 1, 1, 'role1'), (1, 1, 1, 'role2'), (1, 2, 0, 'role1'), (1, 3, 0, 'rolex'), (2, 2, 1, 'role1'), (2, 2, 1, 'role2'), (2, 3, 0, 'rolex'), (3, 3, 1, 'role1'), (3, 4, 0, 'role2') 
insert into @invoice values (1), (1), (1), (2), (2), (3), (3), (3), (3), (3) 

は、したがって、この例のために、我々は3名を持って、彼らは複数のオフィスに属しているが、唯一のメインオフィスの各が、一部の人は、オフィスごとに複数の役割を持っています。彼らはそれぞれ複数の請求書を作成しています。

私は一人あたりの請求書の数を取得することができます:返す

select 
    i.personid, 
    count(*) InvoiceCountByPerson 
from 
    @invoice i 
inner join 
    @person p on p.personid = i.personid 
group by 
    i.personid 

personid InvoiceCountByPerson 
-------------------------------- 
    1    3 
    2    2 
    3    5 

を私はメインオフィス名で請求書の数を取得する必要があります。

officename InvoiceCountByOfficeName 
------------------------------------ 
office1    3 
office2    2 
office3    5 

これは動作しません:

主たる事務所3枚の請求書、主たる事務所2枚の請求書を作成しoffice2あるPERSON2を作成office1で、その本社Person3は5枚の請求書を作成しoffice3ので、期待された結果であるPERSON1
select 
    o.officename, 
    count(*) InvoiceCountByOfficeName 
from 
    @invoice i 
inner join 
    @person p on p.personid = i.personid 
inner join 
    @personoffice po on po.personid = p.personid AND po.mainoffice = 1 
inner join 
    @office o on o.officeid = po.officeid 
group by 
    o.officename 

それが返されますよう:

officename InvoiceCountByOfficeName 
------------------------------------- 
office1     6 
office2     4 
office3     5 

を同じ人物が異なる役割を持つ複数のmainoffice = 1つのレコードを持っているように、私は@personof上の個別のいくつかの並べ替えを持っている必要があります被害者は加入する。何百万もの請求書もパフォーマンスを考慮する必要があります。

+0

よくフォーマットされたSQLの質問を読むたびに嬉しいです:-)。関連するすべての詳細を含めるためだけに+1してください。 –

+0

'内部結合(別名を選択... @personofficeから)'? –

+0

最初の本店に請求書が必要ですか? – DhruvJoshi

答えて

2

あなたは、あなたがしなければならなかったのではなく、直接@personofficeテーブルを使用しての派生テーブルを使用している...ので、接近している:

select 
    o.officename, 
    count(*) InvoiceCountByOfficeName 
from 
    @invoice i 
inner join 
    @person p on p.personid = i.personid 
inner join 
    (
     select distinct personid, officeid 
     from @personoffice 
     where mainoffice = 1 
    ) 
    po on po.personid = p.personid 
inner join 
    @office o on o.officeid = po.officeid 
group by 
    o.officename 

結果:

officename InvoiceCountByOfficeName 
---------- ------------------------ 
office1 3 
office2 2 
office3 5 
+0

これは派生テーブルを1回だけ実行するか、1人につき1回だけ実行するのでしょうか? – curious

+0

派生テーブルは、メインselect句の各行に対して実行されるサブクエリ(select句の中で選択)に並行して一度だけ実行されます。 –

1
select 
     o.officename, 
     count(*) InvoiceCountByOfficeName 
    from 
     @invoice i 
    inner join 
     @person p on p.personid = i.personid 
    inner join 
     (
     select distinct personid,officeid,mainoffice from @personoffice 
     ) po on po.personid = p.personid AND po.mainoffice = 1 
    inner join 
     @office o on o.officeid = po.officeid 
    group by 
     o.officename 

おかげ

+0

これは、派生テーブル内のwhere句として 'mainoffice = 1'conditionを置く方が良いでしょう。 –

関連する問題