I am looking for a union query to produce one total not two..ideas? - sql

I am not the greatest at writing SQL. I wrote this in Access and then went to SQL view. Took both queries and did a union all between them. I keep getting a total from each query. How do I get just one total for each product line.
Results:
Prod Line Period Amount
Cash Discounts 12 -1404010.46
CASH DISCOUNTS 12 1541.19
Freight 12 4050823.43
Freight 12 6817.27
INK 12 -24467.76
INK 12 44414.29
Want
Cash discounts -1402469.27
Freight 405764.70
INK 24467.76
SQL
SELECT [JE Details].[Prod Line], [JE Details].Period, Sum([JE Details].Amount) AS Amount
FROM [JE Details]
GROUP BY [JE Details].[Prod Line], [JE Details].Period
HAVING ((([JE Details].Period)=12))
UNION ALL
SELECT [AP Details].[Product Line], [AP Details].[Fiscal Period], Sum([AP Details].
[Invoice Amt]) AS Amount
FROM [AP Details]
GROUP BY [AP Details].[Product Line], [AP Details].[Fiscal Period]
HAVING ((([AP Details].[Fiscal Period])=12));

How about:
SELECT [Prod Line], Sum(Amount)
FROM
(SELECT [Prod Line], Amount
FROM [JE Details]
WHERE Period=12
UNION ALL
SELECT [Product Line] ,[Invoice Amt]
FROM [AP Details]
WHERE [Fiscal Period]=12) q
GROUP BY [Product Line]

Related

Why does my record count increase as my denominator for a division performed in a nested query increases?

In my query I'm trying to calculate the total overtime worked by employees by dividing basic salary by 173(hours in a month) which gives me the hourly rate then dividing the total overtime amount of employee by the hourly rate. To my surprise the record count increases as the number of hours in a month increases, should it not decrease?
Here's my script:
select 'Employees that worked more overtime' [CAAT],*
from ( select H.[Month]
,H.[Employee Code]
,H.[Department]
,H.[Job title]
,H.[Surname]
,H.[Full Names]
,H.[Basic Salary]
,R.[Overtime]
,H.[Hourly Rate]
,round(R.[Overtime] / H.[Hourly Rate],2) [Overtime Hours]
from (select [Month]
,[Employee Code]
,Department
,[Job title]
,[Surname]
,[Full Names]
,nullif(convert(money,[Amount]),0.00) [Basic Salary]
,nullif(round(convert(money,[Amount]) / 173,2),0.00) [Hourly Rate]
from [Salary DB]
where [Field Desc] = 'ED01-Basic Salary') H
left join
(select [Month]
,[Employee Code]
,nullif(sum(convert(money,[Amount])),0.00) [Overtime]
from [Salary DB]
where [Field Desc] in ('ED02-O/Time 1.5','ED02-O/Time 2.0','ED42-Sunday Pay')
group by [Month]
,[Employee Code]) R
on H.[Employee Code] = R.[Employee Code]
and H.[Month] = R.[Month]) [Data]
where [Overtime Hours] > '40'
Order by [Employee Code], [Month] Desc

Calculate AVG in SQL Select statement when some values are NULL

I have struggled to find a solution to this problem, so any help would be hugely appreciated.
I have two tables, lets call one table_a and one table_b, representing two possible sources of customer orders. They both contain a field called "customer_number" which I am using to outer join table_b to table_a. I am then calculating an average customer order size given the two tables.
Where i struggle is where a customer has an entry in either table, but not in both. Then my average calc returns NULL.
Table_a:
Customer Number
Total Online Orders
123456789
1350
987654321
650
Table_b:
Customer Number
Total InStore Orders
123456789
350
So basically the second customer does not have an entry in table_b.
My code as follows:
select distinct
a.[customer number],
a.[Total Online Orders],
b.[Total InStore Orders],
coalesce(a.[Total Online Orders] + b.[Total InStore Orders]) / 2 as [Average Order Size]
from table_a a
full outer join table_b b on a.[customer number]=b.[customer number]
Results table:
Customer Number
Total Online Orders
Total InStore Orders
Average Order Size
123456789
1350
350
850
987654321
650
NULL
NULL
I basically want the results table to show 650 for customer 987654321. Any ideas what I am doing wrong?
thanks!
You can use the brute force method:
( coalesce(a.[Total Online Orders], 0) + coalesce(b.[Total InStore Orders], 0)) /
nullif(case when a.[Total Online Orders] is not null then 1 else 0 end +
case when b.[Total InStore Orders] is not null then 1 else 0 end, 0)
)
) as [Average Order Size]
Use COALESCE() for the values of the 2 columns twice:
(
coalesce(a.[Total Online Orders], b.[Total InStore Orders]) +
coalesce(b.[Total InStore Orders], a.[Total Online Orders])
) / 2 as [Average Order Size]
Consider UNION as well, which handles a few other cases too, especially where customer number isn't necessarily unique in each table:
WITH cte (xtype, [customer number], order_amt) AS (
select 1 AS xtype, [customer number], [Total Online Orders] FROM table_a UNION ALL
select 2 AS xtype, [customer number], [Total InStore Orders] FROM table_b
)
SELECT [customer number]
, SUM(CASE WHEN xtype = 1 THEN order_amt ELSE 0 END) AS [Total Online Orders]
, SUM(CASE WHEN xtype = 2 THEN order_amt ELSE 0 END) AS [Total InStore Orders]
, AVG(order_amt) AS [Average Order Size]
FROM cte
GROUP BY [customer number]
ORDER BY [customer number]
;

Aggregated sub query inside other aggregated query

I use Microsoft VBA together with Excel and also use the ADODB connection to treat the Sheet as database.
I have one issue regarding a SQL aggregated query that uses also aggregated sub queries. The issue is that I cannot use it like this, due to the fact it is throwing errors and I don't know how to change it
The SQL query:
Select inv.[Region], inv.[Org Name], inv.[Bill To Customer Number], inv.[Bill To Customer Name],
SUM(inv.[AR Global Total Amount]) as "Amount Invoiced",
COUNT(pay.[Sales Invoice Number]) as "Count Invoices",
SUM(inv.[AR Global Total Amount]*(inv.[Payment Due Fiscal Date]-inv.[Invoiced Fiscal Date])) as "Sum of Terms Mult",
SUM(inv.[AR Global Total Amount]*(pay.GL_Min-inv.[Invoiced Fiscal Date])) as "Sum of Pay Days Mult",
SUM(inv.[AR Global Total Amount]*(pay.GL_Min-inv.[Payment Due Fiscal Date])) as "Sum of Days Late Mult"
FROM
(
Select *
From [Data$] as inv
WHERE [AR Transaction Sub Type] IN ('Inv', 'Inv-T')
) a,
(
Select [Region], [Org Name], [Bill To Customer Number], [Bill To Customer Name], [Sales Invoice Number], Min([GL Fiscal Date]) as GL_Min
FROM [Data$] as pay
WHERE [AR Transaction Sub Type] IN ('Cash', 'Cash-T')
GROUP BY [Region], [Org Name], [Bill To Customer Number], [Bill To Customer Name], [Sales Invoice Number]
) t
WHERE inv.[Sales Invoice Number] = pay.[Sales Invoice Number] AND inv.[Org Name] = pay.[Org Name] AND inv.[AR Global Total Amount]>0
GROUP BY inv.[Region], inv.[Org Name], inv.[Bill To Customer Number], inv.[Bill To Customer Name]
ORDER BY SUM(inv.[AR Global Total Amount]) DESC
The problem is on the second sub query, the one where I try to capture the min date.
Could someone point me to a proper syntax?
Thanks!
Your query seems correct except subquery alias. Could you try this?
Select inv.[Region], inv.[Org Name], inv.[Bill To Customer Number], inv.[Bill To Customer Name],
SUM(inv.[AR Global Total Amount]) as "Amount Invoiced",
COUNT(pay.[Sales Invoice Number]) as "Count Invoices",
SUM(inv.[AR Global Total Amount]*(inv.[Payment Due Fiscal Date]-inv.[Invoiced Fiscal Date])) as "Sum of Terms Mult",
SUM(inv.[AR Global Total Amount]*(pay.GL_Min-inv.[Invoiced Fiscal Date])) as "Sum of Pay Days Mult",
SUM(inv.[AR Global Total Amount]*(pay.GL_Min-inv.[Payment Due Fiscal Date])) as "Sum of Days Late Mult"
FROM
(
Select *
From [Data$] as inv
WHERE [AR Transaction Sub Type] IN ('Inv', 'Inv-T')
) inv,
(
Select [Region], [Org Name], [Bill To Customer Number], [Bill To Customer Name], [Sales Invoice Number], Min([GL Fiscal Date]) as GL_Min
FROM [Data$] as pay
WHERE [AR Transaction Sub Type] IN ('Cash', 'Cash-T')
GROUP BY [Region], [Org Name], [Bill To Customer Number], [Bill To Customer Name], [Sales Invoice Number]
) pay
WHERE inv.[Sales Invoice Number] = pay.[Sales Invoice Number] AND inv.[Org Name] = pay.[Org Name] AND inv.[AR Global Total Amount]>0
GROUP BY inv.[Region], inv.[Org Name], inv.[Bill To Customer Number], inv.[Bill To Customer Name]
ORDER BY SUM(inv.[AR Global Total Amount]) DESC

Query to aggregate contract line-item values across contracts

I have 2 tables in Microsoft Access: Contract_1 & Contract Items
Contract_1 has columns like: Contract ID, Contract Value, Date, Committed Prod_ID, an example of their values will be:
1 $100,000 3/5/15 111
Contract Items has Prod ID, Product, Unit Price an example of their values will be:
111 Light Bulb $5.00
They are linked by a One to Many relationship, Prod ID {PK} to Committed Prod_ID in Contract_1.
When I write a query to show a summary of the products and total price, I get
Product| Unit Price| Quantity| Total Price|
Light Bulb| $5.00| 2| $10.00
Light Bulb| $5.00| 3| $15.00
In my data i have 2 Contracts, contract ID 1 and 5, that both purchased light bulbs. But since they are the same product, how can I make them appear as a total of 5 instead of 3 and 2?
I tried using GROUP BY, but it does not work. My current query looks like this:
SELECT [Contract Items].Product,
[Contract Items].[Unit Price],
Contract_1.[Actual Qty] AS Quantity,
[Unit Price]*[Quantity] AS [Total Price]
FROM [Contract Items]
INNER JOIN Contract_1
ON [Contract Items].[Prod ID]=Contract_1.[Committed Prod_ID]
GROUP BY [Contract Items].Product,
[Contract Items].[Unit Price],
Contract_1.[Actual Qty],
[Contract Items].[Quantity];
Thanks!
Try this(EDITED), what #jarlh is saying :
SELECT [Contract Items].Product,
[Contract Items].[Unit Price],
SUM(Contract_1.[Actual Qty]) AS Quantity,
SUM([Contract Items].[Unit Price]*Contract_1.[Actual Qty]) AS [Total Price]
FROM [Contract Items]
INNER JOIN Contract_1
ON [Contract Items].[Prod ID]=Contract_1.[Committed Prod_ID]
GROUP BY [Contract Items].Product,
[Contract Items].[Unit Price];
In that case first get the count and then do a join and calculate the total price like below
SELECT [Contract Items].Product,
[Contract Items].[Unit Price],
tab.Quantity,
[Contract Items].[Unit Price] * tab.[Quantity] AS [Total Price]
FROM [Contract Items]
INNER JOIN
(
SELECT Committed Prod_ID,
count(*) as Quantity
FROM Contract_1
GROUP BY Committed Prod_ID
) tab ON [Contract Items].[Prod ID]=tab.[Committed Prod_ID]

Access Query + your query does not include the specified expression 'TimeID' as part of the aggregate function

I'm getting the following error when I try to run my query
your query does not include the specified expression 'TimeID' as part of the aggregate function
INSERT INTO dwSalesFacts ( FactID, TimeID, CustomerID, EmployeeID, LocationID, ProductID, Quantity, UnitPrice, Discount )
SELECT COUNT(FactID), dwTime.TimeID, Orders.[Customer ID], Orders.[Employee ID], dwLocation.LocationID, [Order Details].[Product ID], [Order Details].Quantity, [Order Details].[Unit Price], [Order Details].Discount
FROM Orders, dwTime, dwLocation, [Order Details];
Since you have COUNT(FactID) in your SELECT statement you need to specify the GROUP BY like so:
GROUP BY dwTime.TimeID, Orders.[Customer ID],
Orders.[Employee ID], dwLocation.LocationID,
[Order Details].[Product ID], [Order Details].Quantity,
[Order Details].[Unit Price], [Order Details].Discount
Whether or not that is what you want the count grouped on I don't know, but based on your select that is what it would have to be.
If FactID is an autonumber field then you don't even need to specify it. Try the following:
INSERT INTO dwSalesFacts (TimeID, CustomerID, EmployeeID, LocationID,
ProductID, Quantity, UnitPrice, Discount)
SELECT t.TimeID, o.[Customer ID], o.[Employee ID], l.LocationID,
od.[Product ID], od.Quantity, od.[Unit Price], od.Discount
FROM Orders AS o, dwTime AS t, dwLocation AS l, [Order Details] AS od