SUM multiple tables GROUP BY column - sql

I have the following SQL Server tables:
create table Cars
(
CarID int,
CarType varchar(50),
PlateNo varchar(20)
);
create table Fuelings
(
CarID int,
FuelingDate date,
Odometer int,
Quantity decimal,
Cost money
);
create table Maintenances
(
CarID int,
MaintenanceDate date,
MaintenanceCost money
);
I'm having problems calculating the fuel consumption grouped by the column CarType. To get the fuel consumption I want to calculate the distance and fuel quantity for each car, then sum that up grouped by the column CarType.
What I have now:
SELECT DISTINCT C.CarType AS [Car type],
SUM(M.MaintenanceCost) AS [Maintenance],
SUM(F.Cost) AS [Fuel],
(MAX(Odometer)-MIN(Odometer)) AS [Distance],
(SUM(Quantity)*100)/(MAX(Odometer)-MIN(Odometer)) AS [L/100km]
FROM Cars AS C
LEFT JOIN Maintenances AS M ON M.CarID=C.CarID
AND M.MaintenanceDate BETWEEN '2021-01-01 00:00:00' AND '2021-01-31 23:59:29'
LEFT JOIN Fuelings AS F ON F.CarID=C.CarID
AND F.FuelingDate BETWEEN '2021-01-01 00:00:00' AND '2021-01-31 23:59:29'
GROUP BY C.CarType
Desired result for type 'SUV':
Total fuel quantity: 301
Total distance: 1600
Consumption: 18,8125
See here: http://sqlfiddle.com/#!18/2636c/18

I used a common table expression cte_car to make a first grouping and get all the details of a single car. Then a final grouping is done to get the totals accross the car types.
Sample data
I left out the Maintenances table because it is not needed for the consumptions.
create table Cars
(
CarID int,
CarType varchar(50),
PlateNo varchar(20)
);
insert into Cars (CarID, CarType, PlateNo) values
(1,'Coupe','BC18341'),
(2,'Hatchback','AU14974'),
(3,'Hatchback','BC49207'),
(4,'SUV','AU10299'),
(5,'Coupe','AU32703'),
(6,'Coupe','BC51719'),
(7,'Hatchback','AU30325'),
(8,'SUV','BC52018');
create table Fuelings
(
CarID int,
FuelingDate date,
Odometer int,
Quantity decimal,
Cost money
);
insert into Fuelings (CarID, FuelingDate, Odometer, Quantity, Cost) values
(1,'2021-01-02', 124520, 53.28, 78.32),
(1,'2021-01-15', 124810, 49.17, 68.34),
(1,'2021-01-28', 125130, 51.74, 69.13),
(2,'2021-01-05', 344380, 49.10, 72.81),
(2,'2021-01-18', 344540, 54.98, 69.37),
(2,'2021-01-29', 344990, 52.76, 66.83),
(3,'2021-01-01', 874200, 45.27, 73.48),
(3,'2021-01-19', 874770, 46.75, 67.91),
(3,'2021-01-26', 874930, 52.15, 75.50),
(4,'2021-01-03', 414190, 50.88, 71.72),
(4,'2021-01-14', 414400, 51.94, 68.15),
(4,'2021-01-29', 415140, 48.30, 77.82),
(5,'2021-01-06', 294240, 48.15, 71.48),
(5,'2021-01-19', 294680, 53.86, 66.80),
(5,'2021-01-30', 294890, 51.54, 74.31),
(6,'2021-01-01', 934220, 49.26, 69.98),
(6,'2021-01-18', 934520, 51.35, 71.50),
(6,'2021-01-25', 934970, 54.63, 65.72),
(7,'2021-01-05', 584110, 51.42, 74.29),
(7,'2021-01-22', 584430, 49.36, 69.95),
(7,'2021-01-31', 584750, 49.84, 73.18),
(8,'2021-01-02', 654280, 53.87, 77.75),
(8,'2021-01-17', 654730, 45.32, 67.48),
(8,'2021-01-29', 654930, 50.75, 69.80);
Solution
with cte_car as
(
select c.CarId,
c.CarType,
max(f.Odometer) - min(f.Odometer) as CarDistance,
sum(f.Quantity) as CarQuantity
from Cars c
join Fuelings f
on f.CarId = c.CarId
group by c.CarId,
c.CarType
)
select cc.CarType,
sum(cc.CarDistance) as TotalDistance,
sum(cc.CarQuantity) as TotalQuantity,
sum(cc.CarQuantity) * 100.0 / sum(cc.CarDistance) as TotalConsumption
from cte_car cc
group by cc.CarType;
Result
CarType TotalDistance TotalQuantity TotalConsumption
------- ------------- ------------- ----------------
Coupe 2010 463 23.034825
Hatchback 1980 451 22.777777
SUV 1600 301 18.8125
Fiddle to see things in action.

Related

SQL Server Stored Procedure for Menu Performance Report

I have four tables in my SQL database i.e MenuItems, Categories, Invoices and InvoiceDetails. Now what I want is to show the menu performance report for a certain date i.e total Qty and total Amount for
each menu item for a specific date. It shows the desired result without the date in the where clause but excludes menu items with null values.
Here is my stored procedure:
CREATE PROCEDURE spGetMenuPerformanceByDay
#Date date,
#Terminal int
AS
BEGIN
SELECT
M.Name,
ISNULL(SUM(D.Amount), 0) AS Amount,
ISNULL(SUM(D.Qty), 0) AS Qty
FROM
MenuItems AS M
JOIN
Categories AS C ON C.Id = M.CategoryId
LEFT JOIN
InvoiceDetails AS D ON M.Id = D.ItemId
LEFT JOIN
Invoices I ON I.Id = d.InvoiceId
WHERE
#Terminal IN (I.TerminalId, C.TerminalId)
AND CONVERT(date, I.Time) = #Date
OR NULL IN (Amount, Qty)
GROUP BY
M.Name, M.Id, D.ItemId
ORDER BY
(Qty) DESC
END
The result this stored procedure returns on adding Date in where clause:
Item
Amount
Qty
KOFTA ANDA
1950
3
HOT N SOUR SOUP
550
1
CHICKEN CHOWMEIN
250
1
CHICKEN KORMA
850
1
And the result I want is but don't get it on adding Date in where clause :
Item
Amount
Qty
KOFTA ANDA
1950
3
HOT N SOUR SOUP
550
1
CHICKEN CHOWMEIN
250
1
CHICKEN KORMA
850
1
CRISPY CHICKEN
0
0
MEXICAN BURGER
0
0
What if you don't put criteria for Invoices in the WHERE clause?
Sample data
create table Categories (
Id int primary key,
Name varchar(30) not null,
TerminalId int not null
);
create table MenuItems (
Id int identity(21,1) primary key,
Name varchar(30) not null,
CategoryId int not null,
foreign key (CategoryId) references Categories(Id)
);
create table Invoices (
Id int identity(31,1) primary key,
TerminalId int not null,
ItemId int not null,
Time datetime,
foreign key (ItemId) references MenuItems(Id)
);
create table InvoiceDetails (
InvoiceDetailId int identity(41,1) primary key,
InvoiceId int,
Amount decimal(10,2),
Qty int,
foreign key (InvoiceId) references Invoices(Id)
);
insert into Categories (Id, Name, TerminalId) values
(1,'KOFTA', 1),
(2,'SOUP', 1),
(3,'CHICKEN', 1),
(4,'BURGER', 1);
insert into MenuItems (CategoryId, Name) values
(1,'KOFTA ANDA'),
(2,'HOT N SOUR SOUP'),
(3,'CHICKEN CHOWMEIN'),
(3,'CHICKEN KORMA'),
(3,'CRISPY CHICKEN'),
(4,'MEXICAN BURGER');
insert into Invoices (ItemId, TerminalId, Time)
select itm.Id, cat.TerminalId, GetDate() as Time
from MenuItems itm
join Categories cat on cat.Id = itm.CategoryId
where itm.Name in (
'KOFTA ANDA',
'HOT N SOUR SOUP',
'CHICKEN CHOWMEIN',
'CHICKEN KORMA'
);
insert into InvoiceDetails (InvoiceId, Amount, Qty) values
(31, 1950, 3),
(32, 550, 1),
(33, 250, 1),
(34, 850, 1);
Query
DECLARE #TerminalId INT = 1;
DECLARE #Date DATE = GetDate();
SELECT
V.[Date],
C.Name AS Category,
M.Name AS MenuItemName,
ISNULL(SUM(D.Amount), 0) AS Amount,
ISNULL(SUM(D.Qty), 0) AS Qty
FROM Categories AS C
CROSS JOIN (SELECT #Date AS [Date], #TerminalId AS TerminalId) V
JOIN MenuItems AS M
ON M.CategoryId = C.Id
LEFT JOIN Invoices I
ON I.ItemId = M.Id
AND I.TerminalId = V.TerminalId
AND CAST(I.Time AS DATE) = V.[Date]
LEFT JOIN InvoiceDetails AS D
ON D.InvoiceId = I.Id
WHERE C.TerminalId = V.TerminalId
GROUP BY V.[Date], C.Id, M.Id, C.Name, M.Name
ORDER BY SUM(D.Qty) DESC
Date
Category
MenuItemName
Amount
Qty
2021-12-18
KOFTA
KOFTA ANDA
1950.00
3
2021-12-18
SOUP
HOT N SOUR SOUP
550.00
1
2021-12-18
CHICKEN
CHICKEN CHOWMEIN
250.00
1
2021-12-18
CHICKEN
CHICKEN KORMA
850.00
1
2021-12-18
CHICKEN
CRISPY CHICKEN
0.00
0
2021-12-18
BURGER
MEXICAN BURGER
0.00
0
Demo on db<>fiddle here
Here's my crack at your goal. Notice the changes. I found the reference to TerminalId in Category table highly suspicious - so much that I suspect it is a model flaw. Along those lines I note that TerminalId should likely have a foreign key to a missing table for Terminals. So I ignore that.
With that out, references to Category are now irrelevant. So that was removed as well. I also changed the procedure name since I find the reference to "day" misleading. It is highly likely "menu performance" would be evaluated on a "day" basis since retail (especially food service) sales vary by day of week consistently. So let's not mislead anyone thinking that is what this procedure does.
For simplicity and clarity, I removed the ISNULL usage. Add it back if desired but such things are usually better handled by the consumer of the resultset. I left the ORDER BY clause as a stub for you to re-evaluate (and you need to).
So how does this work? Simply calculate the sums directly in the CTE and then outer join from the menu items to the CTE sums to get all menu items along with the relevant performance information for the date specified.
CREATE PROCEDURE dbo.GetMenuPerformanceByDate
#Date date,
#Terminal int
AS
BEGIN
with sales as (
select det.ItemId, SUM(det.Amount) as amt, SUM(det.Qty) as qty
from dbo.Invoices as inv
inner join dbo.InvoiceDetails as det
on inv.Id = det.InvoiceId
where cast(inv.Time as date) = #Date
and inv.TerminalId = #Terminal
group by det.ItemId
)
select menu.name, sales.amt, sales.qty
from dbo.MenuItems as menu
left join sales
on menu.Id = sles.ItemId
order by ...
;
END;
One last note. This filter:
cast(inv.Time as date) = #Date
is generally not a good method of filtering a datetime column. Far better to use inclusive lower and exclusive upper boundaries like:
inv.Time >= #date and inv.Time < dateadd(day, 1, #date)
for this reason.
My last note - there is a potential flaw regarding MenuItems. Presumably "name" is unique. It is highly unlikely that multiple rows would have the same name, but "unlikely" is not a restriction. If you generate rows based on name and name turns out to NOT be unique, your results are difficult to interpret.

Join Sales table with Sales Region table based on Sales person and the date of the sale

I have a table of sales, but it does not include the region of the sale. I also have a table of the assignment of our sales people based on the region and dates they were assigned. I want to join the tables so I can grab the region and include it into my sales table.
I join on the sales person's initial (key), but I also want to compare the date of the sale to the region start and region stop to join the correct region. I tried using the sale date BETWEEN the start and stop, but that did not work because if they are still currently in the region, it provides a NULL value.
Thanks for any help, Brent
IF NOT EXISTS (
select * from sysobjects where name='sales' and xtype='U'
)CREATE TABLE sales (
[Sale_Date] DATETIME,
[Sales_Person] NVARCHAR(3),
[Sales_Amount] INT,
[Region] INT
);
INSERT INTO sales VALUES
('2016-07-01 00:00:00',N'MDD',152,NULL),
('2016-09-21 00:00:00',N'MDD',278,NULL),
('2018-03-01 00:00:00',N'STE',385,NULL),
('2018-04-01 00:00:00',N'MDD',426,NULL),
('2019-02-25 00:00:00',N'MDD',224,NULL),
('2020-02-15 00:00:00',N'STE',261,NULL),
('2020-03-01 00:00:00',N'STE',480,NULL),
('2020-06-05 00:00:00',N'BBB',245,NULL),
('2020-07-05 00:00:00',N'BBB',178,NULL);
IF NOT EXISTS (
select * from sysobjects where name='SalesPersonAssignment' and xtype='U'
) CREATE TABLE SalesPersonAssignment (
[sales_person] NVARCHAR(4),
[Region_ID] INT,
[Region_Name] NVARCHAR(6),
[Region_Start_Date] DATETIME,
[Region_Stop_Date] NVARCHAR(10)
);
INSERT INTO SalesPersonAssignment VALUES
(N'MDD',2,N'North ','2015-01-05 00:00:00',N'12/31/2017'),
(N'MDD',6,N'West','2018-01-01 00:00:00',N'NULL'),
(N'STE ',6,N'West','2018-10-02 00:00:00',N'12/31/2019'),
(N'STE',2,N'North ','2020-01-01 00:00:00',N'NULL'),
(N'BBB',1,N'South','2019-01-01 00:00:00',N'NULL');
Select s.Sale_Date, s.Sales_Amount, s.Sales_Person, spa.Region_Name
FROM sales s LEFT OUTER JOIN SalesPersonAssignment spa ON s.Sales_Person = spa.sales_person
--join based on the sales date and region's start/stop date of the sales person
You are storing a date as a string. And the time component is unnecessary. The better approach is:
CREATE TABLE SalesPersonAssignment (
[sales_person] NVARCHAR(4),
[Region_ID] INT,
[Region_Name] NVARCHAR(6),
[Region_Start_Date] DATE,
[Region_Stop_Date] DATE
);
 
INSERT INTO SalesPersonAssignment VALUES
(N'MDD',2,N'North ','2015-01-05','2017-12-31'),
(N'MDD',6,N'West','2018-01-01', NULL),
(N'STE ',6,N'West','2018-10-02', '2019-12-31'),
(N'STE',2,N'North ','2020-01-01', NULL),
(N'BBB',1,N'South','2019-01-01', NULL);
Just include those conditions in the ON clause:
SELECT s.Sale_Date, s.Sales_Amount, s.Sales_Person, spa.Region_Name
FROM sales s LEFT OUTER JOIN
SalesPersonAssignment spa
ON s.Sales_Person = spa.sales_person AND
s.Sale_Date >= spa.Region_Start_Date AND
(s.Sale_Date <= spa.Region_End_Date OR spa.Region_End_Date IS NULL);

Joining tables with recent date for each row then weighted averaging

There are three tables, such as equip_type , output_history, and time_history in Oracle DB.
Is there a way to join the three tables as shown below at (1) and then to get weighted average as shown below at (2)?
--equip_type table and the date
CREATE TABLE equip_type (
EQUIP_TYPE VARCHAR(60),
EQUIP VARCHAR(60)
);
INSERT INTO equip_type VALUES ('A','e1');
-- output_history and data
CREATE TABLE output_history (
EQUIP VARCHAR(60),
MODEL VARCHAR(60),
Data1 VARCHAR(60),
QUANTITY NUMBER(10)
);
INSERT INTO output_history VALUES ('e1','m1','20180103',10);
INSERT INTO output_history VALUES ('e1','m1','20180106',20);
--time_history table and data
CREATE TABLE time_history (
EQUIP VARCHAR(60),
MODEL VARCHAR(60),
Data2 VARCHAR(60),
time NUMBER(10)
);
INSERT INTO time_history VALUES ('e1','m1','20180101',6);
INSERT INTO time_history VALUES ('e1','m1','20180105',5);
(1) How to get joined table as below?
EQUIP MODEL DATE1 QUANTITY DATE2 TIME TYPE
---- ---- ---------- ------ -------- ---- ----
e1 m1 20180103 10 20180101 6 A
e1 m1 20180106 20 20180105 5 A
For each row in OUTPUT_HISTORY, *the most recent row at the point of the DATE1*in TIME_HISTORY is joined.
(2) Then, With the joined table above, how to get weighted average of TIME?
(QUANTITY * TIME) / sum of QUANTITY group by TYPE, MODEL
for example,(10×6 + 20×5)÷(10+20) for equip type A and model m1
One method uses analytic functions to get the most recent record and then simple aggregation
select sum(quantity * time) / sum(quantity)
from output_history oh left join
(select th.*,
row_number() over (partition by equip, model order by date2 desc) as seqnum
from time_history th
) th
on oh.equip = th.equip and oh.model = th.model and th.seqnum = 1
group by equip, model;

Making Queries for relaional model

I have some troubles with making queries for this task. anyone please help me.
Cars(License, Brand, Year);
Employees(EID, Firstname, Lastname, Wage);
Customers(CID, Firstname, Lastname, Phone);
OfficeStaff(EID, OfficeNumber);
Own(CID, License);
Mechanic(EID, HourlyPrice);
Repairs(License, EID, PartCost, Hours);
Create SQL statements performing the following tasks:
(a) Create the OfficeStaff-table while taking into account that the OfficeNumber may not be NULL and must be in
the range [1..10].
(b) Find the name(s), i.e. firstname(s) and lastname(s), of the owner(s) of the car(s), which have been repaired for
the most times.
(c) Find the average number of hours spent (i.e. Repairs.Hours) repairing cars of brand “Opel”.
(d) Update the HourlyPrice to be 20 EUR for all mechanics with a wage of 100 EUR or more.
My tries:
(a) Create the OfficeStaff-table while taking into account that the OfficeNumber may not be NULL and must be in the range [1..10].
CREATE TABLE OfficeStaff (
EID INT PRIMARY KEY,
Firstname TEXT,
Lastname TEXT,
Wage REAL,
OfficeNumber INT NOT NULL,
CONSTRAINT CK_OfficeNumber CHECK (OfficeNumber BETWEEN 1 AND 10)
b) no idea?!
(c) Find the average number of hours spent (i.e. Repairs.Hours) repairing cars of brand “Opel”.
SELECT AVG(R.Hours)
FROM Repairs R, Cars C
WHERE R.License = C.License AND C.Brand = “Opel”
(d) Update the HourlyPrice to be 20 EUR for all mechanics with a wage of 100 EUR or more.
UPDATE Mechanic
SET HourlyPrice = 20
WHERE Wage >= 100
(a) how to create can look here
CREATE TABLE OfficeStaff (
EID INT PRIMARY KEY,
Firstname varchar(100),
Lastname varchar(100),
Wage decimal(15,2),
OfficeNumber INT NOT NULL,
CONSTRAINT CK_OfficeNumber CHECK (OfficeNumber BETWEEN 1 AND 10)
)
(b) Not sure about this one, but you have to use rank to get not only 1 value among same values. For this you can look here
WITH cte AS (
SELECT a.Firstname, a.Lastname, rank() OVER (ORDER BY count(c.Hours)) AS rnk
from Customers as a
join Own as b
on a.CID=b.CID
join Repairs as c
on b.License = c.License
group by a.Firstname, a.Lastname
)
SELECT *
FROM cte
WHERE rnk <= 1;
(c) join usage here
SELECT AVG(R.Hours)
FROM Repairs R
join Cars C
on R.license=C.license
WHERE C.Brand = 'Opel'
(d) update usage here and here
UPDATE Mechanic
SET HourlyPrice = 20
from Employees
WHERE Mechanic.EID = Employees.EID
AND Employees.Wage >= 100

Query matching stock trading buyers/sellers based on conditions

I'm trying to create a stored procedure that matches buyers and sellers for a fake stock market program. I eventually I'd like to use this to populate a transaction table to finalize peoples orders. This would also be in a SQL Server Agent Job. Here's the table I have:
Id UserId Type QtyRemaining Price CreatedOn
1 3 BUY 50 1.00 2012-09-09 05:25:48.4470000
2 6 BUY 50 1.00 2012-09-09 19:25:34.4300000
3 5 SELL 30 1.00 2012-09-09 19:22:59.5900000
4 3 SELL 50 0.90 2012-09-09 06:39:34.9100000
5 2 SELLALL 50 1.00 2012-09-09 04:10:01.8400000
There are several conditions that need to be satisfied to make these matches:
A buyer must look for a seller that has >= amount of shares that the buyer wants if its a 'SELL' order. If its a 'SELLALL' order then the Qty must be equal for the buyer to buy the stock. E.g. The seller must be selling 50 shares and the buyer MUST be buying 50 shares at the same price or lower.
A buyer wants the minimum price for the stock.
If there are multiple sellers with the conditions above a buyer takes the oldest selling stock first after the minimum price.
So the pairs of traders would be #1 and #4, #2 and #5. Therefore #3 would still be pending.
Here's the code I was playing around with but I can't get it to match up properly with the minimum price and the oldest first:
select o.*, oa.*, r.* from [Order] o
join OrderActivity oa on o.Id = oa.OrderId
join (
select o2.Id, o2.VideoId, o2.UserId, oa2.Price, oa2.QtyRemaining, o2.[Type] from [Order] o2
join OrderActivity oa2 on o2.Id = oa2.OrderId
where o2.Type = 'buy' and oa2.Status = 'open'
) as r on (o.VideoId = r.VideoId and oa.Price <= r.Price and r.QtyRemaining = oa.QtyRemaining and o.UserId != r.UserId)
where (o.Type = 'sell' or o.Type = 'sellall') and oa.Status = 'open'
try this
Briefly ,
1.Rank buyer based on the createddate(named as stocks in the below query) 2.Rank seller based on the price,createddate(named as lowNoldstock)3.Get the matching rank
select stocks.*,lowNoldStock.*
from (select *,row_number() over(order by createdon) as buyerrank
from stocktable(nolock) where c='buy' ) stocks
inner join
(select *,row_number() over(order by price,createdon) as sellerrank
from stocktable(nolock) where [type]='sell' or [type]='sellall' ) lowNoldstock
on (stocks.qty<=lowNoldStock.qty and lowNoldStock.type='sell')
or (lowNoldStock.type='sellall' and stocks.qty=lowNoldStock.qty and stocks.price>=lowNoldStock.price)
where lowNoldStock.sellerrank=stocks.buyerrank
test script in sql fiddle ,for some reason it is showing partial result in sql fiddle
This works in my local database
You are welcome to play with this:
declare #Transactions as Table
( Id Int, UserId Int, Type VarChar(8), QtyRemaining Int, Price Money, CreatedOn DateTime )
insert into #Transactions ( Id, UserId, Type, QtyRemaining, Price, CreatedOn ) values
( 1, 3, 'BUY', 50, 1.00, '2012-09-09 05:25:48.447' ),
( 2, 6, 'BUY', 50, 1.00, '2012-09-09 19:25:34.430' ),
( 3, 5, 'SELL', 30, 1.00, '2012-09-09 19:22:59.590' ),
( 4, 3, 'SELL', 50, 0.90, '2012-09-09 06:39:34.910' ),
( 5, 2, 'SELLALL', 50, 1.00, '2012-09-09 04:10:01.840' )
-- Split the transactions into temporary working tables.
declare #Buyers as Table
( Id Int, UserId Int, Type VarChar(8), QtyRemaining Int, Price Money, CreatedOn DateTime )
declare #Sellers as Table
( Id Int, UserId Int, Type VarChar(8), QtyRemaining Int, Price Money, CreatedOn DateTime )
insert into #Buyers
select Id, UserId, Type, QtyRemaining, Price, CreatedOn
from #Transactions
where Type = 'BUY'
insert into #Sellers
select Id, UserId, Type, QtyRemaining, Price, CreatedOn
from #Transactions
where Type like 'SELL%'
-- Process the buy orders in the order in which they were created.
declare #BuyerId as Int = ( select top 1 Id from #Buyers order by CreatedOn )
declare #SellerId as Int
declare #Balance as Int
while #BuyerId is not NULL
begin
-- Pair a seller, if possible, with the current buyer.
; with Willard as (
select Row_Number() over ( order by S.Price, S.CreatedOn ) as Priority,
S.Id as S_Id, S.QtyRemaining as S_QtyRemaining,
B.QtyRemaining as B_QtyRemaining
from #Sellers as S inner join
#Buyers as B on B.Id = #BuyerId and
case
when S.Type = 'SELL' and B.QtyRemaining <= S.QtyRemaining then 1
when S.Type = 'SELLALL' and B.QtyRemaining = S.QtyRemaining then 1
else 0
end = 1
)
select #SellerId = S_Id, #Balance = S_QtyRemaining - B_QtyRemaining
from Willard
where Priority = 1
-- Display the result.
select #BuyerId as BuyerId, #SellerId as SellerId, #Balance as RemainingShares
-- Update the working tables.
if #Balance = 0
delete from #Sellers
where Id = #SellerId
else
update #Sellers
set QtyRemaining = #Balance
where Id = #SellerId
delete from #Buyers
where Id = #BuyerId
-- Find the next buy order.
set #BuyerId = ( select top 1 Id from #Buyers order by CreatedOn )
end
-- Display any unfilled orders.
select 'Unmatched Buy', *
from #Buyers
select 'Unmatched Sell', *
from #Sellers