简体   繁体   中英

SQL Server Roll-up (Sum) Value from associative table

I have the following situation. I have a “Client” Table (Parent) and an “Opportunity” Table Child table. (See example below).

Client Table

| Id   | Name     
------------------
|1     | Client A 
|2     | Client B 
|3     | Client C 

Opportunity Table

| Id   | ClientId       |   Value
---------------------------------
| 10   | 1              |   1000 
| 11   | 1              |   3000 
| 12   | 2              |   1500 
| 13   | 3              |   2000 

I want to show sum of all Total of Opportunity Value (OppValue) on the client record.

Expected Output

| Id   | Name     |   OppValue 
-----------------------------
|1     | Client A |     4000 
|2     | Client B |     1500 
|3     | Client C |     2000 

The business requirement is to filter on “OppValue” with the following criteria greater than, less than or null, etc but not by opportunity create date, etc. We are expecting each year users will be adding 500 clients and 45000 new opportunities. Based on the above I can think of three options

  1. Calculate OppValue using SQL Query (Group By or Partition By)
  2. Create View or Calculated Field using UDF
  3. Create a new field in the “Client” table and populate it using Application business logic (outside SQL).

Which of the solution in your opinion will work best in terms of User experience (speed) and maintenance? In case there is a better suggestion please let me know.

Many thanks in advance.

Start with a view:

create view client_opp as (
     select c.*, o.oppvalue
     from client c outer apply
          (select sum(oppvalue) as oppvalue
           from opportunities o
           where o.clientId = c.clientId
          ) o;

Be sure you have an index on opportunities(clientId, oppvalue) -- or at least on opportunities(clientId) . Note that this uses apply quite specifically so the view should work well even when used in a query with additional filtering.

If this works performance-wise, then you are done. Other methods using triggers and UDFs require a bit more maintenance in the database. You can definitely use them, but I would recommend waiting to see if this meets your performance needs.

Try the following query using inner join and sum() function. To know more about inner join you can follow this link . You can learn in detail about the Aggregate Functions (Transact-SQL) here .

Create table Client
(Id int, Name Varchar(20))

insert into Client values
(1, 'Client A'),
(2, 'Client B'),
(3, 'Client C')


create table Opportunity
(Id int, ClientId int, Value int)

insert into Opportunity values
(10, 1, 1000 ),
(11, 1, 3000 ),
(12, 2, 1500 ),
(13, 3, 2000 )

Select Client.Id, Client.Name, sum(Value) as Value
from Client
inner join Opportunity on Client.Id = Opportunity.ClientId       
group by Client.Id, Client.Name

Output

Id  Name       Value
----------------------
1   Client A    4000
2   Client B    1500
3   Client C    2000

To create a view you can use the following create view example.

Syntax:

Create View <ViewName> 
as
<View Query>

Example:

create view MyView
as
Select Client.Id, Client.Name, sum(Value) as Value
from Client
inner join Opportunity on Client.Id = Opportunity.ClientId       
group by Client.Id, Client.Name

Selecting the result from a view as created above.

select * from MyView 

You can use apply :

create view client_view as
     select c.*, ot.OppValue
     from ClientTable c cross apply
          ( select sum(value) as OppValue 
            from OpportunityTable ot 
            where ot.ClientId = c.ClientId
          ) ot;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM