Fixing the payout issue - sql

I am re-posting my original question with edits, as that question was answered and best answer chosen.
Payments comes from our supplier which goes towards the accounts and the reps get paid based on which account got how much.
Customers Table (Usage is kwH)
+----+----------+------------+----------+----------+----------+-------+-------+
| ID | Customer | Account_no | Meter_no | Supplier | Active | Usage | Repid |
+----+----------+------------+----------+----------+----------+-------+-------+
| 1 | Joe | 123 | 111 | NSTAR | active | 20 | 100 |
| 2 | Joe | 123 | 222 | NSTAR | active | 30 | 100 |
| 3 | Joe | 123 | 150 | NSTAR | inactive | 60 | 100 |
| 4 | Sam | 456 | 352 | SEP | active | 50 | 100 |
| 5 | Jill | 789 | 222 | FES | active | 40 | 200 |
| 6 | Mike | 883 | 150 | ABB | inactive | 40 | 200 |
+----+----------+------------+----------+----------+----------+-------+-------+
Payment_Receive (table)
+------------+----------+-------------+-------------+
| Account_no | Supplier | Amount_paid | PaymentDate |
+------------+----------+-------------+-------------+
| 123 | NSTAR | 20 | 2011-11-01 |
| 456 | SEP | 40 | 2011-11-01 |
| 456 | SEP | -40 | 2011-11-01 |
| 456 | SEP | 40 | 2011-11-01 |
| 789 | FES | 50 | 2011-11-01 |
| 883 | ABB | 30 | 2011-11-01 |
+------------+----------+-------------+-------------+
The two tables are used for rep payout. Payment are recieved for each account, they are matched with our customers based on Account_No and Supplier. We do not have control over the payment_table because it comes from outside. This creates certain problems because we can not do one-to-one match between the two tables. Leaving that aside, I would like to have payout calculated for RepID = 100 with certain criteria. This is the output I would like to see for RepId = 100
+------------+----------+-------------+-------------+-------------+
| Account_no | Supplier | Amount_paid | Usage | PaymentDate |
+------------+----------+-------------+-------------+-------------+
| 123 | NSTAR | 20 | 60* | 2011-11-01 |
| 456 | SEP | 40 | 50 | 2011-11-01 |
| 456 | SEP | -40 | 40 | 2011-11-01 |
| 456 | SEP | 40 | 40 | 2011-11-01 |
+------------+----------+-------------+-------------+-------------+
Note here that
Account_no 123 exists thrice in customers table, it must show one time in rep payout
3 amounts were paid to account_no 456, all the three must show in the report
*60 = Notice that there are 2 active records (and one inactive). This could be the sum of the two active. But any other value is acceptable if that makes the query easy (for greater of the two or one, not the other)
Note that Usage column must appear in the output table, This is the column that creates problem for me. If I dont include this everything works fine.
The point with Usage column, if I have two records for same customer having same Account_No and Supplier but different usage, that makes the two records distinct when I include usage column. Therefore distinct does not work to remove this duplicate.
Reports are calculated on Monthly basis
Script for the question
create database testcase
go
use testcase
go
create table customers (
id int not null primary key identity,
customer_name varchar(25),
account_no int,
meter_no int,
supplier varchar(20),
active varchar(20),
usage int,
repid int
)
create table payments_received (
account_no int,
supplier varchar(20),
amount_paid float,
paymentdate smalldatetime
)
insert into customers values('Joe',123, 111,'NSTAR','active',20,100)
insert into customers values('Joe',123, 222,'NSTAR','active',30, 100)
insert into customers values('Joe',123, 150,'NSTAR','inactive',60,100)
insert into customers values('Sam',456, 352,'SEP','active',40,100)
insert into customers values('Jill',789, 222,'FES','active',40,200)
insert into customers values('Mike',883, 150,'ABB','inactive',40,200)
select * from customers
insert into payments_received values(123,'NSTAR',20,'2011-11-01')
insert into payments_received values(456,'SEP',40,'2011-11-01')
insert into payments_received values(456,'SEP',-40,'2011-11-01')
insert into payments_received values(456,'SEP',40,'2011-11-01')
insert into payments_received values(789,'FES',50,'2011-11-01')
insert into payments_received values(883,'ABB',30,'2011-11-01')
select * from payments_received

How about this:
CREATE VIEW v_customers_by_rep
AS
SELECT SUM(USAGE) AS USAGE ,
REPID ,
CAST(account_no AS VARCHAR) + '_' + Supplier AS UniqueId
FROM customers
GROUP BY CAST(account_no AS VARCHAR) + '_' + Supplier ,
REPID
GO
DECLARE
#repid INT
SET #repid = 100
SELECT pr.* ,
u.Usage
FROM payments_received pr INNER JOIN v_customers_by_rep u
ON CAST(pr.account_no AS VARCHAR) + '_' + pr.Supplier = u.UniqueId
WHERE u.repid = #repid
You could also eliminate inactive records in the view if desired.

Related

How to join two tables in one view?

I am trying to create a view where I can see the items that have been planned to be shipped and have not been shipped, and the items have have been shipped but were not planned to.
In order to do this I have 2 tables with different data in them.
Table SC (actually shipped):
+---------+-----------------+----------------------+-------------+
| item_id | source_location | destination_location | shipped_qty |
+---------+-----------------+----------------------+-------------+
| 001 | California | South_Carolina | 80 |
+---------+-----------------+----------------------+-------------+
| 001 | California | South_Carolina | 0 |
+---------+-----------------+----------------------+-------------+
| 001 | California | Texas | 20 |
+---------+-----------------+----------------------+-------------+
| 003 | Texas | South_Carolina | 200 |
+---------+-----------------+----------------------+-------------+
| 004 | South_Carolina | Texas | 30 |
+---------+-----------------+----------------------+-------------+
| 004 | South_Carolina | Texas | 10 |
+---------+-----------------+----------------------+-------------+
Table SO (plan to ship items):
+---------+-----------------+----------------------+---------------+
| item_id | source_location | destination_location | planned_order |
+---------+-----------------+----------------------+---------------+
| 001 | California | South_Carolina | 100 |
+---------+-----------------+----------------------+---------------+
| 001 | California | South_Carolina | 100 |
+---------+-----------------+----------------------+---------------+
| 001 | California | Texas | 10 |
+---------+-----------------+----------------------+---------------+
| 003 | Texas | South_Carolina | 200 |
+---------+-----------------+----------------------+---------------+
| 004 | South_Carolina | Texas | 300 |
+---------+-----------------+----------------------+---------------+
| 004 | South_Carolina | Texas | 50 |
+---------+-----------------+----------------------+---------------+
So in this case, for example, since the item 001 has three different planned orders from California to South Carolina, I don't want it to show all the three orders in the view, I want it to be only in one row, but sum all the planned orders together, as showed below.
Desired Outcome:
+---------+----------------+-----------------+-------------+-------------+
| item_id | source_loc | destination_loc | shipped_qty | planned_qty |
+---------+----------------+-----------------+-------------+-------------+
| 001 | California | South_Carolina | 80 | 200 |
+---------+----------------+-----------------+-------------+-------------+
| 001 | California | Texas | 20 | 10 |
+---------+----------------+-----------------+-------------+-------------+
| 003 | Texas | South_Carolina | 200 | 200 |
+---------+----------------+-----------------+-------------+-------------+
| 004 | South_Carolina | Texas | 40 | 350 |
+---------+----------------+-----------------+-------------+-------------+
I have tried this so far:
SELECT o.source_location,
o.destination_location,
o.item_id,
o.planned_order,
c.shipped_qty
FROM SO_TRANSFER o, SC_TRANSFER c
But this hasn't worked since the shipped_qty does not match the item and this code also does not add the orders together.
By the way, I am using Microsoft SQL Server 2012.
Thank you!
I think you want:
select coalesce(s.item_id, p.item_id) as item_id,
coalesce(s.source_location, p.source_location) as source_location,
coalesce(s.destination_location, p.destination_location) as destination_location,
coalesce(s.shipped_qty, 0) as shipped_qty,
coalesce(planned_qty, 0) as planned_qty
from (select item_id, source_location, destination_location, sum(shipped_qty) as shipped_qty
from sc
group by item_id, source_location, destination_location
) s full join
(select item_id, source_location, destination_location, sum(planned_qty) as planned_qty
from so
group by item_id, source_location, destination_location
) p
on s.item_id = p.item_id and
s.source_location = p.source_location and
s.destination_location = p.destination_location;
You can try this:
SELECT A.item_id,
A.source_location AS source_loc,
A.destination_location AS destination_loc,
A.shipped_qty,
B.planned_order
FROM
(SELECT item_id,source_location,destination_location,SUM(shipped_qty)
AS shipped_qty
FROM SC GROUP BY item_id,source_location,destination_location) A,
(SELECT item_id,source_location,destination_location,SUM(planned_order)
AS planned_order
FROM SO GROUP BY item_id,source_location,destination_location) B
WHERE A.item_id = B.item_id AND
A.source_location= B.source_location AND
A.destination_location= B.destination_location
EDIT: I just realize my answer is similar to Gordon Linoff's answer, and his answer got more feature such as handling data that exists in one table only using COALESCE in T-SQL and FULL JOIN property. Since I worked 1 hour for this answer, so I will just leave it here.
The point is you should SUM(quantity) from each table first, then you can easy JOIN 2 table with condition:
ON so.item_id = sc.item_id AND so.source_loc = sc.source_loc AND so.destination_loc = sc.destination_loc
The following query will do what you are looking for
Create table #SC(
item_id varchar(50),
source_location varchar(max),
Destination_location varchar(max),
Shipped_qty int)
insert into #SC values('001','california','sourth_carolian',80)
insert into #SC values('001','california','sourth_carolian',0)
insert into #SC values('001','california','Texas',20)
insert into #SC values('003','Texas','sourth_carolian',200)
insert into #SC values('004','sourth_carolian','Texas',30)
insert into #SC values('004','sourth_carolian','Texas',10)
--select * from #SC
Create table #SO(
item_id varchar(50),
source_location varchar(max),
Destination_location varchar(max),
Planned_order int)
insert into #SO values('001','california','sourth_carolian',100)
insert into #SO values('001','california','sourth_carolian',100)
insert into #SO values('001','california','Texas',10)
insert into #SO values('003','Texas','sourth_carolian',200)
insert into #SO values('004','sourth_carolian','Texas',300)
insert into #SO values('004','sourth_carolian','Texas',50)
--select * from #SO
select C.item_id,C.source_location,C.Destination_location, sum(C.Shipped_qty) as Shipped_qty, po.planned_order from #SC C
outer apply
(select sum(Planned_order) as planned_order from #SO
where source_location+Destination_location=C.source_location+C.Destination_location
group by item_id,source_location,Destination_location ) as PO
group by C.item_id,C.source_location,C.Destination_location,po.planned_order
You can create a SELECT statement, and use that as a table in the FROM clause:
SELECT o.source_location,
o.destination_location,
o.item_id,
o.planned_order,
c.shipped_qty_sum
FROM SO_TRANSFER o
INNER JOIN (SELECT SUM(shipped_qty) AS shipped_qty_sum,
source_location,
item_id
FROM SC_TRANSFER
GROUP BY source_location, item_id) c
ON o.item_id = c.item_id AND o.source_location = c.source_location

T-SQL return individual values instead of cumulative value

I have a 1 table in a db that stored Incoming, Outgoing and Net values for various Account Codes over time. Although there is a date field the sequence of events per Account Code is based on the "Version" number where 0 = original record for each Account Code and it increments by 1 after each change to that Account Code.
The Outgoing and Incoming values are stored in the db as cumulative values rather than the individual transaction value but I am looking for a way to Select * From this table and return the individual amounts as opposed to the cumulative.
Below are test scripts of table and data, and also 2 examples.
If i Select where code = '123' in the test table I currently get this (values are cumulative);
+------+------------+---------+---------+---------+-----+
| Code | Date | Version | Incoming| Outgoing| Net |
+------+------------+---------+---------+---------+-----+
| 123 | 01/01/2018 | 0 | 100 | 0 | 100 |
| 123 | 07/01/2018 | 1 | 150 | 0 | 150 |
| 123 | 09/01/2018 | 2 | 150 | 100 | 50 |
| 123 | 14/01/2018 | 3 | 200 | 100 | 100 |
| 123 | 18/01/2018 | 4 | 200 | 175 | 25 |
| 123 | 23/01/2018 | 5 | 225 | 175 | 50 |
| 123 | 30/01/2018 | 6 | 225 | 225 | 0 |
+------+------------+---------+---------+---------+-----+
This is what I would like to see (each individual transaction);
+------+------------+---------+----------+----------+------+
| Code | Date | Version | Incoming | Outgoing | Net |
+------+------------+---------+----------+----------+------+
| 123 | 01/01/2018 | 0 | 100 | 0 | 100 |
| 123 | 07/01/2018 | 1 | 50 | 0 | 50 |
| 123 | 09/01/2018 | 2 | 0 | 100 | -100 |
| 123 | 14/01/2018 | 3 | 50 | 0 | 50 |
| 123 | 18/01/2018 | 4 | 0 | 75 | -75 |
| 123 | 23/01/2018 | 5 | 25 | 0 | 25 |
| 123 | 30/01/2018 | 6 | 0 | 50 | -50 |
+------+------------+---------+----------+----------+------+
If I had the individual transaction values and wanted to report on the cumulative, I would use an OVER PARTITION BY, but is there an opposite to that?
I am not looking to redesign the create table or the process in which it is stored, I am just looking for a way to report on this from our MI environment.
Note: I've added other random Account Codes into this to emphasis how the data is not ordered by Code or Version, but by Date.
thanks in advance for any help.
USE [tempdb];
IF EXISTS ( SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'Table1'
AND TABLE_SCHEMA = 'dbo')
DROP TABLE [dbo].[Table1];
GO
CREATE TABLE [dbo].[Table1]
(
[Code] CHAR(3)
,[Date] DATE
,[Version] CHAR(3)
,[Incoming] DECIMAL(20,2)
,[Outgoing] DECIMAL(20,2)
,[Net] DECIMAL(20,2)
);
GO
INSERT INTO [dbo].[Table1] VALUES
('123','2018-01-01','0','100','0','100'),
('456','2018-01-02','0','50','0','50'),
('789','2018-01-03','0','0','0','0'),
('456','2018-01-04','1','100','0','100'),
('456','2018-01-05','2','150','0','150'),
('789','2018-01-06','1','50','50','0'),
('123','2018-01-07','1','150','0','150'),
('456','2018-01-08','3','200','0','200'),
('123','2018-01-09','2','150','100','50'),
('789','2018-01-10','2','0','0','0'),
('456','2018-01-11','4','225','0','225'),
('789','2018-01-12','3','75','25','50'),
('987','2018-01-13','0','0','50','-50'),
('123','2018-01-14','3','200','100','100'),
('654','2018-01-15','0','100','0','100'),
('456','2018-01-16','5','250','0','250'),
('987','2018-01-17','1','50','50','0'),
('123','2018-01-18','4','200','175','25'),
('789','2018-01-19','4','100','25','75'),
('987','2018-01-20','2','150','125','25'),
('321','2018-01-21','0','100','0','100'),
('654','2018-01-22','1','0','0','0'),
('123','2018-01-23','5','225','175','50'),
('321','2018-01-24','1','100','50','50'),
('789','2018-01-25','5','100','50','50'),
('987','2018-01-26','3','150','150','0'),
('456','2018-01-27','6','250','250','0'),
('456','2018-01-28','7','270','250','20'),
('321','2018-01-29','2','100','100','0'),
('123','2018-01-30','6','225','225','0'),
('987','2018-01-31','4','175','150','25')
;
GO
SELECT *
FROM [dbo].[Table1]
WHERE [Code] = '123'
GO;
USE [tempdb];
IF EXISTS ( SELECT *
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'Table1'
AND TABLE_SCHEMA = 'dbo')
DROP TABLE [dbo].[Table1];
GO;
}
Just use lag():
select Evt, Date, Version,
(Loss - lag(Loss, 1, 0) over (partition by evt order by date)) as incoming,
(Rec - lag(Rec, 1, 0) over (partition by evt order by date)) as outgoing,
(Net - lag(Net, 1, 0) over (partition by evt order by date)) as net
from [dbo].[Table1];

DBMS - Oracle | return multiple max values for multiple tables / relations

I need to return a list of customers who had ordered maximum number items. I have added the following and get some results but need to filter the query to display multiple maximum values.
DDL
CREATE TABLE Customer
(Cust_Num NUMBER(4) PRIMARY KEY,
Cust_LName VARCHAR2(10),
Cust_FName VARCHAR2(10),
Cust_Address VARCHAR2(20),
Cust_City VARCHAR2(12),
Cust_State VARCHAR2(2),
Cust_Zip VARCHAR2(5),
Cust_Referred NUMBER(4));
Create Table BookOrder
(BO_OrderNum NUMBER(4) PRIMARY KEY,
BO_CustNum NUMBER(4) REFERENCES Customer(Cust_Num),
BO_OrderDate DATE,
BO_ShipDate DATE,
BO_ShipStreet VARCHAR2(18),
BO_ShipCity VARCHAR2(15),
BO_ShipState VARCHAR2(2),
BO_ShipZip VARCHAR2(5));
CREATE TABLE BookOrderItem
(BOI_OrderNum NUMBER(4) NOT NULL REFERENCES BookOrder(BO_OrderNum),
BOI_ItemNum NUMBER(2) NOT NULL,
BOI_ISBN VARCHAR2(10) REFERENCES Book(Book_ISBN),
BOI_Qty NUMBER(3),
CONSTRAINT bookorderitem_pk PRIMARY KEY (BOI_OrderNum, BOI_ItemNum));
I have written the following DML:
SELECT C.CUST_LNAME, C.CUST_FNAME, BO.BO_CUSTNUM, BOI.BOI_ORDERNUM,
COUNT(BOI.BOI_ITEMNUM) AS Total_Items_Per_Order
FROM BookOrderItem BOI JOIN BookOrder BO ON BOI.BOI_OrderNum = BO.BO_OrderNum
JOIN Customer C ON C.Cust_Num = BO.BO_CustNum
GROUP BY C.Cust_LName, C.CUST_FName, BO.BO_CustNum, BOI.BOI_OrderNum
ORDER BY Total_Item_Per_Order DESC;
Which gives me the following results...
+------------+------------+------------+--------------+-----------------------+
| CUST_LNAME | CUST_FNAME | BO_CustNum | BOI_OrderNum | TOTAL_ITEMS_PER_ORDER |
+------------+------------+------------+--------------+-----------------------+
| NELSON | BECCA | 1017 | 1012 | 4 |
| GIANA | TAMMY | 1007 | 1007 | 4 |
| MORALES | BONITA | 1001 | 1003 | 3 |
| MORALES | BONITA | 1001 | 1018 | 2 |
| LUCAS | JAKE | 1010 | 1001 | 2 |
| GIRARD | CINDY | 1005 | 1009 | 2 |
| LEE | JASMINE | 1014 | 1013 | 1 |
| MONTIASA | GREG | 1018 | 1005 | 1 |
| MONTIASA | GREG | 1018 | 1019 | 1 |
| PIERSON | THOMAS | 1004 | 1008 | 1 |
| JONES | KENNETH | 1008 | 1020 | 1 |
| MCGOVERN | REESE | 1011 | 1002 | 1 |
| LUCAS | JAKE | 1010 | 1011 | 1 |
| FALAH | KENNETH | 1020 | 1015 | 1 |
| SMITH | JENNIFER | 1019 | 1010 | 1 |
| GIRARD | CINDY | 1005 | 1000 | 1 |
| SMITH | LEILA | 1003 | 1006 | 1 |
| GIANA | TAMMY | 1007 | 1014 | 1 |
| FALAH | KENNETH | 1020 | 1004 | 1 |
| SMITH | LEILA | 1003 | 1016 | 1 |
| SCHELL | STEVE | 1015 | 1017 | 1 |
+------------+------------+------------+--------------+-----------------------+
As per this screenshot...
To only keep the first row(s) you'd use FETCH FIRST n ROW(s) ONLY in Oracle 12c. To consider ties, you'd replace ONLY by WITH TIES:
...
ORDER BY Total_Item_Per_Order DESC
FETCH FIRST 1 ROW WITH TIES;
Please try the following...
SELECT Cust_LName,
Cust_FName,
Cust_Num AS Cust_Num,
BO_OrderNum AS Order_Num,
BOI_ItemNum AS Item_Num,
Max_Qty_Per_Order AS Max_Qty_Per_Order
FROM ( SELECT BOI_OrderNum AS Order_Num,
MAX( BOI_Qty ) AS Max_Qty_Per_Order
FROM BookOrderItem
GROUP BY BOI_OrderNum
) Max_Qty_Per_Order_Finder
JOIN BookOrderItem ON BookOrderItem.BOI_OrderNum = Max_Qty_Per_Order_Finder.Order_Num
AND BookOrderItem.BOI_Qty = Max_Qty_Per_Order_Finder.Max_Qty_Per_Order
JOIN BookOrder ON Max_Qty_Per_Order_Finder.Order_Num = BookOrder.BO_OrderNum
JOIN Customer Customer ON Customer.Cust_Num = BookOrder.BO_CustNum
ORDER BY Max_Qty_Per_Order DESC,
BO_OrderNum,
BOI_Item_Num;
This statement starts by creating a list of Order Numbers and the largest value of BOI_Qty associated with each.
The results of this subquery will be joined to BookOrderItem in such a way that only those records from BookOrderItem that have the largest value of BOI_Qty for their BookOrder will be returned. If more than one BookOrderItem for a particular BookOrder has the maximum value of BOI_Qty for that BookOrder, then each such record will be retained.
The resulting dataset is then joined to BookOrder so that the value of BO_CustNum for that BookOrder may be retrieved and be used to join the dataset to Customer, allowing for the Name of a Customer associated with each BookOrder to be retrieved.
The desired fields for each record in our final dataset are then retrieved and sorted.
Please note that I have included the field BOI_ItemNum in the selected fields as you asked for each record that has the maximum value of BOI_Qty to be returned. Without it such records would appear to be repeated. Including BOI_ItemNum will allow you to identify each record returned.
If you have any questions or comments, then please feel free to post a Comment accordingly.

How do I identify Interaction in a column and take sum based on values in two other columns?

I have 3 Tables-
Table 1
Customer ID | Date | Score | Score Factor
------------+------------+-------+-------------
100 | 2014-10-10 | 15 | .25
100 | 2014-12-12 | 25 | .35
100 | 2014-08-08 | 35 | .65
100 | 2014-09-08 | 45 | .55
100 | 2014-01-10 | 15 | .25
100 | 2014-12-12 | 75 | .85
100 | 2014-08-08 | 85 | .65
100 | 2015-09-08 | 45 | .55
200 | 2014-10-10 | 45 | .25
200 | 2014-12-12 | 55 | .35
200 | 2014-08-08 | 35 | .65
200 | 2014-09-08 | 45 | .55
200 | 2014-01-10 | 55 | .25
Table 2
Score | Group# | Group Label
-------+--------+-----------+
10 | 1 | Superior |
15 | 1 | Superior |
25 | 1 | Superior |
35 | 2 | Mediocre |
55 | 2 | Mediocre |
65 | 3 | Poor |
75 | 3 | Poor |
85 | 4 | Critical |
Table 3
Interaction | Group label | Group label | Final Score Factor
-------------+--------------+--------------+--------------
INT1 | Superior | Medicocre | .80
INT2 | Superior | Poor | .90
INT3 | Poor | Critical | .95
Based on these tables, here's what I need to find
Identify whether a 'score' for a 'customer ID' belongs to any group for a particular Year
From Table 1 and Table 2-
Customer 100 for year 2014 has scores of-
15, 25 - Group label "Superior"
35 - Group label "Mediocre"
45 - No Group
Once The Groups have been identified, From Table 3, identify if the groups have Interactions and Map Corresponding 'Final Score Factor'.
Customer 100 has score which belong to Group label "Superior" and "Mediocre". Therefore, INT1 exists and Corresponding 'score factor' is .80.
So the expected result table should be as follows-
Customer ID | Date | Score| Score Factor| Group#| Group label| Interaction | Final Score Factor
-------------+------------+------+-------------+--------+-----------+--------------+------------------
100 | 2014-10-10 | 15 | .25 | 1 | Superior | INT1 | .80
100 | 2014-12-12 | 25 | .35 | 1 | Superior | INT1 | .00
100 | 2014-08-08 | 35 | .65 | 2 | Mediocre | INT1 | .00
100 | 2014-08-08 | 45 | .55 | NULL | Null | Null | .55
100 | 2014-12-12 | 75 | .85 | 3 | Poor | INT3 | .95
100 | 2014-08-08 | 85 | .65 | 4 | Critical | INT3 | .00
NOTE:
The 'Final Interaction Score' is accounted only once per interaction. Repeating Values are made equal to .00
If the Score factor does not belong to any Interaction, the same Score is carry forwarded as Final Score Factor (Row 4) in the above example
Now, I have to take the Sum of the 'Final Score Factors' per customer per year.
Therefore from the results table(above),
Resultant Score = .80 + .55 + .95
I don't understand the way you're supposed to map to the Interactions table. I made some table variables for your input as follows:
declare #customers table (id int, thedate date, score int, scorefactor varchar(5) )
insert into #customers values(100,'2014-10-10',15,'.25')
insert into #customers values(100,'2014-12-12',25,'.35')
insert into #customers values(100,'2014-08-08',35,'.65')
insert into #customers values(100,'2014-09-08',45,'.55')
insert into #customers values(100,'2014-01-10',15,'.25')
insert into #customers values(100,'2014-12-12',75,'.85')
insert into #customers values(100,'2014-08-08',85,'.65')
insert into #customers values(100,'2015-09-08',45,'.55')
insert into #customers values(200,'2014-10-10',45,'.25')
insert into #customers values(200,'2014-12-12',55,'.35')
insert into #customers values(200,'2014-08-08',35,'.65')
insert into #customers values(200,'2014-09-08',45,'.55')
insert into #customers values(200,'2014-01-10',55,'.25')
declare #scores table (score int, groupno int, grouplabel varchar(10))
insert into #scores values(10,1,'Superior')
insert into #scores values(15,1,'Superior')
insert into #scores values(25,1,'Superior')
insert into #scores values(35,2,'Mediocre')
insert into #scores values(55,2,'Mediocre')
insert into #scores values(65,3,'Poor')
insert into #scores values(75,3,'Poor')
insert into #scores values(85,4,'Critical')
declare #interactions table(interaction varchar(5), grouplabel1 varchar(10), grouplabel2 varchar(10), finalscorefactor varchar(5))
insert into #interactions values('INT1', 'Superior', 'Mediocre', '.80')
insert into #interactions values('INT2', 'Superior', 'Poor', '.90')
insert into #interactions values('INT3', 'Poor', 'Critical', '.95')
Then, I ran a simple query to match up customer scores to groups for the year 2014:
select distinct c.id, s.grouplabel
from #customers c
inner join #scores s
on c.score = s.score
where thedate < '2015-01-01' and thedate >= '2014-01-01'
The output I get is this:
id | grouplabel
---------------
100 | Critical
100 | Mediocre
100 | Poor
100 | Superior
200 | Mediocre
So I'm getting customer 100 having not just superior and mediocre, but also poor and critical.
Can you explain better how you would match that to the stuff in table 3?

I need to fix payout issue - example given below (re-edited)

Customer Table (usage is kwH)
+----+----------+------------+----------+----------+----------+-------+-------+
| ID | Customer | Account_no | Meter_no | Supplier | Active | Usage | Repid |
+----+----------+------------+----------+----------+----------+-------+-------+
| 1 | Joe | 123 | 111 | NSTAR | active | 20 | 100 |
| 2 | Joe | 123 | 222 | NSTAR | active | 30 | 100 |
| 3 | Joe | 123 | 150 | NSTAR | inactive | 60 | 100 |
| 4 | Sam | 456 | 352 | SEP | active | 50 | 100 |
| 5 | Jill | 789 | 222 | FES | active | 40 | 200 |
| 6 | Mike | 883 | 150 | ABB | inactive | 40 | 200 |
+----+----------+------------+----------+----------+----------+-------+-------+
Payment_Receive (table)
+------------+----------+-------------+-------------+
| Account_no | Supplier | Amount_paid | PaymentDate |
+------------+----------+-------------+-------------+
| 123 | NSTAR | 20 | 2011-11-01 |
| 456 | SEP | 40 | 2011-11-01 |
| 456 | SEP | -40 | 2011-11-01 |
| 456 | SEP | 40 | 2011-11-01 |
| 789 | FES | 50 | 2011-11-01 |
| 883 | ABB | 30 | 2011-11-01 |
+------------+----------+-------------+-------------+
The two tables are use for rep payout. We do not have control over the payout_table because it comes from outside. This creates certain problems because we can not do one-to-one match between the two tables. Leaving that aside, I would like to have payout calculated for RepID = 100 with certain criteria. This is the output I would like to see for RepId = 100
+------------+----------+-------------+-------------+-------------+
| Account_no | Supplier | Amount_paid | Usage | PaymentDate |
+------------+----------+-------------+-------------+-------------+
| 123 | NSTAR | 20 | 60* | 2011-11-01 |
| 456 | SEP | 40 | 50 | 2011-11-01 |
| 456 | SEP | -40 | 40 | 2011-11-01 |
| 456 | SEP | 40 | 40 | 2011-11-01 |
+------------+----------+-------------+-------------+-------------+
Note here that
Account_no 123 exists twice in customers table, it must show one time in rep payout
3 amounts were paid to account_no 456, all the three must show in the report
Reports are calculated on Monthly basis
Script for example (Updated with Usage column)
create database testcase
go
use testcase
go
create table customers (
id int not null primary key identity,
customer_name varchar(25),
account_no int,
meter_no int,
supplier varchar(20),
active varchar(20),
usage int,
repid int
)
create table payments_received (
account_no int,
supplier varchar(20),
amount_paid float,
paymentdate smalldatetime
)
insert into customers values('Joe',123, 111,'NSTAR','active',20,100)
insert into customers values('Joe',123, 222,'NSTAR','active',30, 100)
insert into customers values('Joe',123, 150,'NSTAR','inactive',60,100)
insert into customers values('Sam',456, 352,'SEP','active',40,100)
insert into customers values('Jill',789, 222,'FES','active',40,200)
insert into customers values('Mike',883, 150,'ABB','inactive',40,200)
select * from customers
insert into payments_received values(123,'NSTAR',20,'2011-11-01')
insert into payments_received values(456,'SEP',40,'2011-11-01')
insert into payments_received values(456,'SEP',-40,'2011-11-01')
insert into payments_received values(456,'SEP',40,'2011-11-01')
insert into payments_received values(789,'FES',50,'2011-11-01')
insert into payments_received values(883,'ABB',30,'2011-11-01')
select * from payments_received
Updated: Updated The question and script
Usage been added to Customers table
Usage must appear int the result table
*60 = Notice that there are 2 active records (and one inactive). This could be the sum of the two, the one that is larger. This column is created problem removing duplicates
Two database brand independent options:
option 1:
Select
*
from
Payment_Receive PR
inner join
(select distinct Account_no, Supplier
From Customer where Repid = 100 ) C
on (PR.Account_no = C.Account_no
and PR.Supplier = C.Supplier )
option 2:
Select
*
from
Payment_Receive PR
Where exists
(select *
From Customer C
where
Repid = 100 and
PR.Account_no = C.Account_no and
PR.Supplier = C.Supplier )
with date range:
option 1:
Select
*
from
Payment_Receive PR
inner join
(select distinct Account_no, Supplier
From Customer where Repid = 100 ) C
on (PR.Account_no = C.Account_no
and PR.Supplier = C.Supplier )
where
year(PR.PaymentDate) = 2011 and
month(PR.PaymentDate) = 11
option 2:
Select
*
from
Payment_Receive PR
Where exists
(select *
From Customer C
where
Repid = 100 and
PR.Account_no = C.Account_no and
PR.Supplier = C.Supplier )
and
year(PR.PaymentDate) = 2011 and
month(PR.PaymentDate) = 11
I used a CTE to limit your Customer table, as well as added support for a specific YEAR and MONTH based on your question in a comment.
WITH customersCte AS
(
SELECT id, customer_name, account_no, meter_no, supplier, active, repid
, ROW_NUMBER() OVER (PARTITION BY account_no ORDER BY account_no ASC) AS rowNumber
FROM customers
)
SELECT pr.Account_no, pr.Supplier, pr.Amount_paid, pr.PaymentDate
FROM payments_received AS pr
INNER JOIN customersCte AS c ON pr.account_no = c.account_no
WHERE c.repid = 100
AND c.rowNumber = 1
AND YEAR(pr.PaymentDate) = 2011
AND MONTH(pr.PaymentDate) = 11