Solved

Multiple aggregations in a single result set.

Posted on 2008-06-10
8
227 Views
Last Modified: 2012-05-05
Hi.

I'm in the process of converting a series of reports from Sage Retrieve 4GL to MSSQL/Crystal.

The reports in Sage are built by code (i.e. read a row from the table, add values to temporary storage/totals), rather than SQL (the 4GL db is NOT SQL).

Here are the tables in use.

Head Offices (HO.Code, HO.Name)
Customers (CU.Code, CU.Name, CU.HOCode) CU.HOCode links to HO.Code

Banks (PB.Code, PB.Period) PB.Code links to CU.Code

Tickets (CT.Ticket, CT.Period, CT.Code) CT.Period links to PB.Period and CT.Code links to CU.Code
TicketCasings (TC.Ticket, TC.Casing, TC.Grade) TC.Ticket links to CT.Ticket, TC.Grade links to lookup GR.Grade

Grade (GR.Grade, GR.Summary)

Orders (BO.Order, BO.Period, BO.Code) BO.Period links to PB.Period and BO.Code links to BO.Code
OrderCasings(BOC.Order, BOC.Casing) BOC.Order links to BO.Order


The problem I am having is trying to get SUM()s across 2 different streams. I don't think it is possible.

If it makes any sense, here is the stored procedure I'm using.

The ticket totals are all correct, but the order totals are all wrong.


I think I need to use a temp table and populate it just like I do in the 4GL code.

Or at least use a subselect for the ticket totals. Hmmm.

Any ideas?

Richard.
CREATE PROCEDURE [dbo].[raq_SingleCustomerSterlingBankReport] 
	@Year int,
	@Month int,
	@Customer CHAR(15)
AS
 
DECLARE @Period INT
 
SELECT @Period = (@Year - 1900) * 12 + @Month
 
SELECT
	-- Head Office
	LTRIM(RTRIM(HO.CustomerCode)) AS [Head Office Code], HO.Name AS [Head Office], HO.AddressLines_1 AS [Head Office Address Line 1], HO.AddressLines_2 AS [Head Office Address Line 2], HO.AddressLines_3 AS [Head Office Address Line 3], HO.AddressLines_4 AS [Head Office Address Line 4], HO.Postcode AS [Head Office Postcode], HO.Telephone AS [Head Office Telephone], HO.Facsimile AS [Head Office Fax],
 
	-- Customer
	LTRIM(RTRIM(CU.CustomerCode)) AS [Customer Code], CU.Name AS [Customer], CU.AddressLines_1 AS [Customer Address Line 1], CU.AddressLines_2 AS [Customer Address Line 2], CU.AddressLines_3 AS [Customer Address Line 3], CU.AddressLines_4 AS [Customer Address Line 4], CU.Postcode AS [Customer Postcode], CU.Telephone AS [Customer Telephone], CU.Facsimile AS [Customer Fax],
 
	-- Period Bank Totals
	PB.Period, PB.BankClosedOn, PB.Accepted, PB.Ordered, PB.Purchased,
	PB.SterlingAdjustments, PB.SterlingClose, PB.SterlingMovement, PB.SterlingOpen, PB.SterlingOrders, PB.SterlingPayments, PB.SterlingScrap, PB.SterlingTickets,
	PB.UnitsAccepted, PB.UnitsAdjust, PB.UnitsClose, PB.UnitsCollected, PB.UnitsOpen, PB.UnitsRejected, PB.UnitsSupplied, PB.UnitsValueAccepted, PB.UnitsValueAdjust, PB.UnitsValueClose, PB.UnitsValueOpen, PB.UnitsValueRejected, PB.UnitsValueSupplied,
 
	-- Shared Casing Size Code
	ISNULL(BOC.CasingSizeCode, TC.CasingSizeCode) AS 'CasingSizeCode',
 
	-- Collection Tickets
	CT.TicketNumber,
	COUNT(TC.UniqueID) AS [Casings Collected],
	SUM(CASE WHEN ISNULL(AC.SummaryCode, '') = 'P' THEN 1		ELSE 0 END) AS [Premium Qty Accepted],
	SUM(CASE WHEN ISNULL(AC.SummaryCode, '') = 'P' THEN TC.Price	ELSE 0 END) AS [Premium Value Accepted],
	SUM(CASE WHEN ISNULL(AC.SummaryCode, '') = 'S' THEN 1		ELSE 0 END) AS [Standard Qty Accepted],
	SUM(CASE WHEN ISNULL(AC.SummaryCode, '') = 'S' THEN TC.Price	ELSE 0 END) AS [Standard Value Accepted],
	SUM(CASE WHEN ISNULL(AC.SummaryCode, '') = 'E' THEN 1		ELSE 0 END) AS [Euromould Qty Accepted],
	SUM(CASE WHEN ISNULL(AC.SummaryCode, '') = 'E' THEN TC.Price	ELSE 0 END) AS [Euromould Value Accepted],
	SUM(CASE WHEN ISNULL(TC.RejectCode, '') <> '' THEN 1		ELSE 0 END) AS [Rejected Qty],
	SUM(CASE WHEN ISNULL(TC.RejectCode, '') <> '' THEN - TC.Price	ELSE 0 END) AS [Rejected Value],
 
	-- Bank Orders
	COUNT(BOC.UniqueID) AS [Casings Supplied],
	SUM(CASE WHEN ISNULL(BOC.Grade, '') = 'P' THEN BOC.SuppliedFromStock	ELSE 0 END) AS [Premium Qty Supplied],
	SUM(CASE WHEN ISNULL(BOC.Grade, '') = 'P' THEN BOC.Value			ELSE 0 END) AS [Premium Value Supplied],
	SUM(CASE WHEN ISNULL(BOC.Grade, '') = 'S' THEN BOC.SuppliedFromStock	ELSE 0 END) AS [Standard Qty Supplied],
	SUM(CASE WHEN ISNULL(BOC.Grade, '') = 'S' THEN BOC.Value			ELSE 0 END) AS [Standard Value Supplied],
	SUM(CASE WHEN ISNULL(BOC.Grade, '') = 'E' THEN BOC.SuppliedFromStock	ELSE 0 END) AS [Euromould Qty Supplied],
	SUM(CASE WHEN ISNULL(BOC.Grade, '') = 'E' THEN BOC.Value			ELSE 0 END) AS [Euromould Value Supplied]
 
FROM
	-- Head Office / Customers
	(
		Customers HO
		INNER JOIN
		Customers CU
			ON
				HO.HeadOfficeFlag = 1 -- Is a Head Office
				AND
				CU.ShortName <> 'CLOSED' -- Is not closed
				AND
				CU.PayFrequency <> 6 -- Is not daily clearance
				AND
					(
					CU.Bank = 2 -- Sterling Bank
					OR
					CU.Bank = 4 -- Mixed Bank
					)
				AND
				HO.CustomerCode = CU.HeadOfficeCode
				AND
				CU.CustomerCode = @Customer
	)
 
	-- Period Bank Totals
	LEFT OUTER JOIN
 
	PeriodBanks PB
		ON
			PB.CustomerCode = CU.CustomerCode
			AND
			PB.Period = @Period
 
	-- Merged Orders and Tickets
	LEFT OUTER JOIN
 
	(
		(
			BankOrders BO
			INNER JOIN
			BankOrdersCasings BOC
				ON
					BO.UniqueID = BOC.ParentID
					AND
					BO.OrderPeriod = @Period
		)
 
		FULL OUTER JOIN
 
		(
			CollectionTickets CT
			INNER JOIN
			TicketCasings TC
				ON
					CT.TicketStatus = 11 -- Comleted Ticket
					AND
					CT.HandledAsScrap <> 1 -- Not a scrap ticket
					AND
					CT.UniqueID = TC.ParentID
					AND
					TC.IOCCode <> 'N' -- Casing was received
					AND
					TC.CasingBank <> 1 -- Casing was not unit bank (mixed bank only)
					AND
					CT.TicketPeriod = @Period
			LEFT OUTER JOIN
			AcceptanceCodes AC
				ON
					TC.AcceptCode = AC.AcceptCode
		)
			ON
				BO.CustomerCode = CT.CustomerCode
				AND
				BO.OrderPeriod = CT.TicketPeriod
				AND
				BOC.CasingSizeCode = TC.CasingSizeCode
	)
		ON
			CU.CustomerCode = ISNULL(BO.CustomerCode, CT.CustomerCode)
--			AND
--			PB.Period = ISNULL(BO.OrderPeriod, CT.TicketPeriod)
 
GROUP BY
	CU.CustomerCode, CU.AddressLines_1, CU.AddressLines_2, CU.AddressLines_3, CU.AddressLines_4, CU.CustomerCode, CU.Facsimile, CU.Name, CU.Postcode, CU.Telephone,
	HO.CustomerCode, HO.AddressLines_1, HO.AddressLines_2, HO.AddressLines_3, HO.AddressLines_4, HO.CustomerCode, HO.Facsimile, HO.Name, HO.Postcode, HO.Telephone,
	PB.Accepted, PB.BankClosedOn, PB.Ordered, PB.Period, PB.Purchased,
	PB.SterlingAdjustments, PB.SterlingClose, PB.SterlingMovement, PB.SterlingOpen, PB.SterlingOrders, PB.SterlingPayments, PB.SterlingScrap, PB.SterlingTickets,
	PB.UnitsAccepted, PB.UnitsAdjust, PB.UnitsClose, PB.UnitsCollected, PB.UnitsOpen, PB.UnitsRejected, PB.UnitsSupplied, PB.UnitsValueAccepted, PB.UnitsValueAdjust, PB.UnitsValueClose, PB.UnitsValueOpen, PB.UnitsValueRejected, PB.UnitsValueSupplied,
	CT.TicketNumber,
	TC.CasingSizeCode,
	BOC.CasingSizeCode
 
ORDER BY
	CasingSizeCode,
	TicketNumber
GO

Open in new window

0
Comment
Question by:Richard Quadling
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 2
  • 2
8 Comments
 
LVL 8

Accepted Solution

by:
srnar earned 250 total points
ID: 21750638
Uf, it is long script. Can you post "create table" and some data to be popultated (via insert). Then we can be more helpful on samples. If not you can try to use windowing aggregation functions that can help with sorting e.g. RANK, ROW_ID. See this link

http://msdn.microsoft.com/en-us/library/ms189798.aspx
0
 
LVL 17

Assisted Solution

by:MIKE
MIKE earned 250 total points
ID: 21752164
"...The problem I am having is trying to get SUM()s across 2 different streams. I don't think it is possible.
..."

If I'm understanding your requirement.....you should be able to do "sum across 2 different streams" in "Crystal" by the use of VARIABLES after data is populated into the report from your stored procedure.

 M
0
 
LVL 40

Author Comment

by:Richard Quadling
ID: 21752939
For what it is worth, I fixed it.

I was trying to sum AND merge data at the same time.

I actually wanted to merge pre-summed data.

Here is the working stored procedure.

Thanks for looking.


CREATE PROCEDURE [dbo].[raq_SingleCustomerSterlingBankReport] 
	@Year int,
	@Month int,
	@Customer CHAR(15)
AS
 
DECLARE @Period INT
 
SELECT @Period = (@Year - 1900) * 12 + @Month
 
SELECT DISTINCT
	-- Head Office
	LTRIM(RTRIM(HO.CustomerCode)) AS [Head Office Code], HO.Name AS [Head Office], 
	HO.AddressLines_1 AS [Head Office Address Line 1], HO.AddressLines_2 AS [Head Office Address Line 2], HO.AddressLines_3 AS [Head Office Address Line 3], HO.AddressLines_4 AS [Head Office Address Line 4], 
	HO.Postcode AS [Head Office Postcode], HO.Telephone AS [Head Office Telephone], HO.Facsimile AS [Head Office Fax],
 
	-- Customer
	LTRIM(RTRIM(CU.CustomerCode)) AS [Customer Code], CU.Name AS [Customer], 
	CU.AddressLines_1 AS [Customer Address Line 1], CU.AddressLines_2 AS [Customer Address Line 2], CU.AddressLines_3 AS [Customer Address Line 3], CU.AddressLines_4 AS [Customer Address Line 4], 
	CU.Postcode AS [Customer Postcode], CU.Telephone AS [Customer Telephone], CU.Facsimile AS [Customer Fax],
 
	-- Period Bank Totals
	PB.Period, PB.BankClosedOn, PB.Accepted, PB.Ordered, PB.Purchased,
	PB.SterlingAdjustments, PB.SterlingClose, PB.SterlingMovement, PB.SterlingOpen, PB.SterlingOrders, PB.SterlingPayments, PB.SterlingScrap, PB.SterlingTickets,
	PB.UnitsAccepted, PB.UnitsAdjust, PB.UnitsClose, PB.UnitsCollected, PB.UnitsOpen, PB.UnitsRejected, PB.UnitsSupplied, 
	PB.UnitsValueAccepted, PB.UnitsValueAdjust, PB.UnitsValueClose, PB.UnitsValueOpen, PB.UnitsValueRejected, PB.UnitsValueSupplied,
 
	-- Shared Casing Size Code
	Casings.CasingSizeCode,
	CTS.*,
	BOS.*
 
FROM
	(
		(
		-- Head Office / Customers
			(
			Customers HO 
			INNER JOIN 
			Customers CU 
				ON 
					HO.HeadOfficeFlag = 1 
					AND 
					CU.ShortName <> 'CLOSED' 
					AND 
					CU.PayFrequency <> 6 
					AND 
						(
						CU.Bank = 2 
						OR 
						CU.Bank = 4
						) 
					AND 
					HO.CustomerCode = CU.HeadOfficeCode 
					AND 
					CU.CustomerCode = @Customer
			)
 
		LEFT OUTER JOIN 
 
		-- Period Bank Totals
		PeriodBanks PB 
			ON 
				PB.CustomerCode = CU.CustomerCode 
				AND 
				PB.Period = @Period
		)
 
		LEFT OUTER JOIN
			(
			SELECT 
				ISNULL(BO.OrderPeriod, CT.TicketPeriod) AS Period, 
				ISNULL(BO.CustomerCode, CT.CustomerCode) AS CustomerCode, 
				ISNULL(BOC.CasingSizeCode, TC.CasingSizeCode) AS CasingSizeCode
			FROM
				(
				BankOrders BO 
				INNER JOIN 
				BankOrdersCasings BOC 
					ON 
						BO.UniqueID = BOC.ParentID 
						AND 
						BO.OrderPeriod = @Period 
						AND 
						BO.CustomerCode = @Customer
				)
 
				FULL OUTER JOIN
 
				(
				CollectionTickets CT 
				INNER JOIN 
				TicketCasings TC 
					ON 
						CT.TicketStatus = 11 
						AND 
						CT.HandledAsScrap <> 1 
						AND 
						CT.UniqueID = TC.ParentID 
						AND 
						TC.IOCCode <> 'N' 
						AND 
						TC.CasingBank <> 1 
						AND 
						CT.TicketPeriod = @Period 
						AND 
						CT.CustomerCode = @Customer
				)
				ON 
					BO.CustomerCode = CT.CustomerCode 
					AND 
					BO.OrderPeriod = CT.TicketPeriod 
					AND 
					BOC.CasingSizeCode = TC.CasingSizeCode
			) Casings 
			ON 
				CU.CustomerCode = Casings.CustomerCode 
				AND 
				PB.Period = Casings.Period
	)
 
	LEFT OUTER JOIN
 
	(
	SELECT
		BOC.CasingSizeCode AS 'BankCasingSizeCode',
		SUM(CASE WHEN ISNULL(BOC.Grade, '') = 'P' THEN BOC.SuppliedFromStock	ELSE 0 END) AS [Premium Qty Supplied],
		SUM(CASE WHEN ISNULL(BOC.Grade, '') = 'P' THEN BOC.Value		ELSE 0 END) AS [Premium Value Supplied],
		SUM(CASE WHEN ISNULL(BOC.Grade, '') = 'S' THEN BOC.SuppliedFromStock	ELSE 0 END) AS [Standard Qty Supplied],
		SUM(CASE WHEN ISNULL(BOC.Grade, '') = 'S' THEN BOC.Value		ELSE 0 END) AS [Standard Value Supplied],
		SUM(CASE WHEN ISNULL(BOC.Grade, '') = 'E' THEN BOC.SuppliedFromStock	ELSE 0 END) AS [Euromould Qty Supplied],
		SUM(CASE WHEN ISNULL(BOC.Grade, '') = 'E' THEN BOC.Value		ELSE 0 END) AS [Euromould Value Supplied]
	FROM
		BankOrders BO 
		INNER JOIN 
		BankOrdersCasings BOC 
			ON 
				BO.UniqueID = BOC.ParentID 
				AND 
				BO.OrderPeriod = @Period 
				AND 
				BO.CustomerCode = @Customer
	GROUP BY
		BOC.CasingSizeCode
	) AS BOS 
		ON 
			BOS.BankCasingSizeCode = Casings.CasingSizeCode
 
	LEFT OUTER JOIN
 
	(
	SELECT
		TC.CasingSizeCode AS 'TicketCasingSizeCode',
		CT.TicketNumber,
		COUNT(TC.UniqueID) AS [Casings Collected],
		SUM(CASE WHEN ISNULL(AC.SummaryCode, '') = 'P' THEN 1		ELSE 0 END) AS [Premium Qty Accepted],
		SUM(CASE WHEN ISNULL(AC.SummaryCode, '') = 'P' THEN TC.Price	ELSE 0 END) AS [Premium Value Accepted],
		SUM(CASE WHEN ISNULL(AC.SummaryCode, '') = 'S' THEN 1		ELSE 0 END) AS [Standard Qty Accepted],
		SUM(CASE WHEN ISNULL(AC.SummaryCode, '') = 'S' THEN TC.Price	ELSE 0 END) AS [Standard Value Accepted],
		SUM(CASE WHEN ISNULL(AC.SummaryCode, '') = 'E' THEN 1		ELSE 0 END) AS [Euromould Qty Accepted],
		SUM(CASE WHEN ISNULL(AC.SummaryCode, '') = 'E' THEN TC.Price	ELSE 0 END) AS [Euromould Value Accepted],
		SUM(CASE WHEN ISNULL(TC.RejectCode, '') <> '' THEN 1		ELSE 0 END) AS [Rejected Qty],
		SUM(CASE WHEN ISNULL(TC.RejectCode, '') <> '' THEN - TC.Price	ELSE 0 END) AS [Rejected Value]
	FROM
		CollectionTickets CT
		INNER JOIN
		TicketCasings TC
			ON
				CT.TicketStatus = 11 -- Comleted Ticket
				AND
				CT.HandledAsScrap <> 1 -- Not a scrap ticket
				AND
				CT.UniqueID = TC.ParentID
				AND
				TC.IOCCode <> 'N' -- Casing was received
				AND
				TC.CasingBank <> 1 -- Casing was not unit bank (mixed bank only)
				AND
				CT.TicketPeriod = @Period
				AND
				CT.CustomerCode = @Customer
		LEFT OUTER JOIN
		AcceptanceCodes AC
			ON
				TC.AcceptCode = AC.AcceptCode
	GROUP BY
		TC.CasingSizeCode,
		CT.TicketNumber		
	) AS CTS 
		ON 
			CTS.TicketCasingSizeCode = Casings.CasingSizeCode
ORDER BY
	CasingSizeCode,
	TicketNumber
GO

Open in new window

0
 
LVL 17

Expert Comment

by:MIKE
ID: 21753731
Glad you were able to get it working....

  : )
0
 
LVL 40

Author Comment

by:Richard Quadling
ID: 21755811
The original 4gl app has no SQL. Instead, I had to use a temp table to gather all the data for the reporting. This takes around 10 mins.

With the new SQL db and the above SP, I can get the whole job done in under 60 seconds. And that includes using PHP to talk to Crystal Reports to produce PDF documents!

These last 2 weeks have given me a new lease of life with Crystal. I'm getting to like it.
0

Featured Post

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

In this article I will describe the Backup & Restore method as one possible migration process and I will add the extra tasks needed for an upgrade when and where is applied so it will cover all.
Composite queries are used to retrieve the results from joining multiple queries after applying any filters. UNION, INTERSECT, MINUS, and UNION ALL are some of the operators used to get certain desired results.​
Monitoring a network: why having a policy is the best policy? Michael Kulchisky, MCSE, MCSA, MCP, VTSP, VSP, CCSP outlines the enormous benefits of having a policy-based approach when monitoring medium and large networks. Software utilized in this v…
Sometimes it takes a new vantage point, apart from our everyday security practices, to truly see our Active Directory (AD) vulnerabilities. We get used to implementing the same techniques and checking the same areas for a breach. This pattern can re…

627 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question