combine 3 queries in one - sql

I have 3 queries:
the first one calculate Totals per Qtr and
the other two calculate Totals per Qtr where Receipt Field is [Yes] or [No].
Now I have(example):
qtrTotals
Year / Total / TotalQtr1 / TotalQtr2 / etc...
qtrTotalsReceiptYes
Year / TotalYes / TotalYesQtr1 / TotalYesQtr2 / etc...
qtrTotalsReceiptNo
Year / TotalNo / TotalNoQtr1 / TotalNoQtr2 / etc...
Is it possible to make one query?
qtrTotals
Year / Total / TotalYes / TotalNo / TotalQtr1 / TotalYesQtr1 / TotalNoQtr1 / etc...
MySQL :
All:
TRANSFORM IIf(Sum([price]) Is Null,0,Sum([price])) AS SumPrice
SELECT Format([ExpencesDate],"yyyy") AS [Year], IIf(Sum([SumPrice]) Is Null,0,Sum([SumPrice])) AS TotalPricePerYear
FROM tblExpences
GROUP BY Format([ExpencesDate],"yyyy")
ORDER BY Format([ExpencesDate],"yyyy") DESC
PIVOT Month([ExpencesDate]) In (1,2,3,4,5,6,7,8,9,10,11,12);
Yes:
TRANSFORM IIf(Sum([price]) Is Null,0,Sum([price])) AS SumPrice
SELECT Format([ExpencesDate],"yyyy") AS [Year], IIf(Sum([SumPrice]) Is Null,0,Sum([SumPrice])) AS TotalPricePerYear
FROM tblExpences
WHERE (((tblExpences.ReceiptYesNo)="Yes"))
GROUP BY Format([ExpencesDate],"yyyy")
ORDER BY Format([ExpencesDate],"yyyy") DESC
PIVOT Month([ExpencesDate]) In (1,2,3,4,5,6,7,8,9,10,11,12);
No:
TRANSFORM IIf(Sum([price]) Is Null,0,Sum([price])) AS SumPrice
SELECT Format([ExpencesDate],"yyyy") AS [Year], IIf(Sum([SumPrice]) Is Null,0,Sum([SumPrice])) AS TotalPricePerYear
FROM tblExpences
WHERE (((tblExpences.ReceiptYesNo)="No"))
GROUP BY Format([ExpencesDate],"yyyy")
ORDER BY Format([ExpencesDate],"yyyy") DESC
PIVOT Month([ExpencesDate]) In (1,2,3,4,5,6,7,8,9,10,11,12);
Thank you.
PS.
The tblExpences (Correct Expenses) has [Date] / [Price] / [ReceiptYesNo].
tblExpences
10/3/2017 / 200 / Yes
10/3/2017 / 200 / No
11/3/2017 / 100 / Yes
14/3/2017 / 100 / No
15/4/2017 / 200 / Yes
10/5/2017 / 200 / No

TLDR; Here is a general form how you can make it work.
Select *
From (Query1) as Q1
Join (Query2) as Q2 On 1
Join (Query3) as Q3 On 1;
It should work because the 3 queries are using an aggregation function only thus returning a single row. Therefore, always joining these columns will result in each column joining and forming a single row of multiple columns.

Okay, a different approach. Firstly, I've assumed your three queries are saved as: qryTotalTotal, qryTotalYes, qryTotalNo.
SELECT qryTotalTotal.Year,
qryTotalTotal.TotalPricePerYear AS TotalPerYear,
qryTotalYes.TotalPricePerYear AS TotalPerYearYes,
qryTotalNo.TotalPricePerYear AS TotalPerYearNo,
qryTotalYes.[1]+qryTotalNo.[1] as TotalMonth1,
qryTotalYes.[1] as TotalMonthYes1,
qryTotalNo.[1] as TotalMonthNo1,
qryTotalYes.[2]+qryTotalNo.[2] as TotalMonth2,
qryTotalYes.[2] as TotalMonthYes2,
qryTotalNo.[2] as TotalMonthNo2,
qryTotalYes.[3]+qryTotalNo.[3] as TotalMonth3,
qryTotalYes.[3] as TotalMonthYes3,
qryTotalNo.[3] as TotalMonthNo3,
qryTotalYes.[4]+qryTotalNo.[4] as TotalMonth4,
qryTotalYes.[4] as TotalMonthYes4,
qryTotalNo.[4] as TotalMonthNo4,
qryTotalYes.[5]+qryTotalNo.[5] as TotalMonth5,
qryTotalYes.[5] as TotalMonthYes5,
qryTotalNo.[5] as TotalMonthNo5,
qryTotalYes.[6]+qryTotalNo.[6] as TotalMonth6,
qryTotalYes.[6] as TotalMonthYes6,
qryTotalNo.[6] as TotalMonthNo6,
qryTotalYes.[7]+qryTotalNo.[7] as TotalMonth7,
qryTotalYes.[7] as TotalMonthYes7,
qryTotalNo.[7] as TotalMonthNo7,
qryTotalYes.[8]+qryTotalNo.[8] as TotalMonth8,
qryTotalYes.[8] as TotalMonthYes8,
qryTotalNo.[8] as TotalMonthNo8,
qryTotalYes.[9]+qryTotalNo.[9] as TotalMonth9,
qryTotalYes.[9] as TotalMonthYes9,
qryTotalNo.[9] as TotalMonthNo9,
qryTotalYes.[10]+qryTotalNo.[10] as TotalMonth10,
qryTotalYes.[10] as TotalMonthYes10,
qryTotalNo.[10] as TotalMonthNo10,
qryTotalYes.[11]+qryTotalNo.[11] as TotalMonth11,
qryTotalYes.[11] as TotalMonthYes11,
qryTotalNo.[11] as TotalMonthNo11,
qryTotalYes.[12]+qryTotalNo.[12] as TotalMonth12,
qryTotalYes.[12] as TotalMonthYes12,
qryTotalNo.[12] as TotalMonthNo12
FROM (qryTotalTotal LEFT JOIN qryTotalYes ON qryTotalTotal.Year = qryTotalYes.Year)
LEFT JOIN qryTotalNo ON qryTotalTotal.Year = qryTotalNo.Year;

To my mind your queries and the output you say they give don't agree with each other. It seems like you must do something to combine your months into quarters.
Anyway, in similar style to your second and third queries:
TRANSFORM IIf(Sum([Price]) Is Null,0,Sum([Price])) AS SumPrice
SELECT Year([ExpensesDate]) AS [Year]
FROM tblExpenses, Numbers
WHERE (((Numbers.Number) Between 1 And 4))
GROUP BY Year([ExpensesDate])
PIVOT IIf([Number]=1,"TotalMonth"& [ReceiptYesNo] & Month([ExpensesDate]),IIf([Number]=2,"TotalMonth" & Month([ExpensesDate]),IIf([Number]=3,"TotalPerYear" & [ReceiptYesNo],"TotalPerYear"))) in ("TotalPerYear","TotalPerYearYes","TotalPerYearNo","TotalMonth1","TotalMonthYes1","TotalMonthNo1","TotalMonth2","TotalMonthYes2","TotalMonthNo2","TotalMonth3","TotalMonthYes3","TotalMonthNo3","TotalMonth4","TotalMonthYes4","TotalMonthNo4","TotalMonth5","TotalMonthYes5","TotalMonthNo5","TotalMonth6","TotalMonthYes6","TotalMonthNo6","TotalMonth7","TotalMonthYes7","TotalMonthNo7","TotalMonth8","TotalMonthYes8","TotalMonthNo8","TotalMonth9","TotalMonthYes9","TotalMonthNo9","TotalMonth10","TotalMonthYes10","TotalMonthNo10","TotalMonth11","TotalMonthYes11","TotalMonthNo11","TotalMonth12","TotalMonthYes12","TotalMonthNo12");
I found I had to paste this into a new query as it kept remembering old sort orders for the column headings.
This depends on a new table called Numbers. This needs just a single field called Number and should be populated with (at least) four rows of data holding the numbers: 1, 2, 3 and 4. Like this:
Table: Numbers
Number
------
1
2
3
4
NB: I corrected the spelling of 'Expense', which will mean you either need to tweak your data or my query so they agree.

Related

Postgresql - Aggregate queries inside aggregate queries

I'm working on building a select statement for a sales rep commission report that uses postgresql tables. I want it to show these columns:
-Customer No.
-Part No.
-Month-to-date Qty (MTD Qty)
-Year-to-date Qty (YTD Qty)
-Month-to-date Extended Selling Price (MTD Extended)
-Year-to-date Extended Selling Price (YTD Extended)
The data is in two tables:
Sales_History (one record per invoice and this table includes Cust. No. and Invoice Date)
Sales_History_Items (one record per part no. per invoice and this table includes Part No., Qty and Unit Price).
If I do a simple query that combines these two tables, this is what it looks like:
Date / Cust / Part / Qty / Unit Price
Apr 1 / ABC Co. / WIDGET / 5 / $11
Apr 4 / ABC Co. / WIDGET / 8 / $11.50
Apr 1 / ABC Co. / GADGET / 1 / $30
Apr 7 / XYZ Co. / WIDGET / 3 / $11.50
etc.
This is the final result I want (one line per customer per part):
Cust / Part / Qty / MTD Qty / MTD Sales / YTD Qty / YTD Sales
ABC Co. / WIDGET / 13 / $147 / 1500 / $16,975
ABC Co. / GADGET / 1 / $30 / 7 / $210
XYZ Co. / WIDGET / 3 / $34.50 / 18 / $203.40
I’ve been able to come up with this SQL statement so far, which does not get me the extended selling columns (committed_qty * unit_price) per line and then summarize them by cust no./part no., and that’s my problem:
with mtd as
(SELECT sales_history.cust_no, part_no, Sum(sales_history_items.committed_qty) AS MTDQty
FROM sales_history left JOIN sales_history_items
ON sales_history.invoice_no = sales_history_items.invoice_no where sales_history_items.part_no is not null and sales_history.invoice_date >= '2020-04-01' and sales_history.invoice_date <= '2020-04-30'
GROUP BY sales_history.cust_no, sales_history_items.part_no),
ytd as
(SELECT sales_history.cust_no, part_no, Sum(sales_history_items.committed_qty) AS YTDQty
FROM sales_history left JOIN sales_history_items
ON sales_history.invoice_no = sales_history_items.invoice_no where sales_history_items.part_no is not null and sales_history.invoice_date >= '2020-01-01' and sales_history.invoice_date <= '2020-12-31' GROUP BY sales_history.cust_no, sales_history_items.part_no),
mysummary as
(select MTDQty, YTDQty, coalesce(ytd.cust_no,mtd.cust_no) as cust_no,coalesce(ytd.part_no,mtd.part_no) as part_no
from ytd full outer join mtd on ytd.cust_no=mtd.cust_no and ytd.part_no=mtd.part_no)
select * from mysummary;
I believe that I have to nest another couple of aggregate queries in here that would group by cust_no, part_no, unit_price but then have those extended price totals (qty * unit_price) sum up by cust_no, part_no.
Any assistance would be greatly appreciated. Thanks!
Do this in one go with filter expressions:
with params as (
select '2020-01-01'::date as year, 4 as month
)
SELECT h.cust_no, i.part_no,
SUM(i.committed_qty) AS YTDQty,
SUM(i.committed_qty * i.unit_price) as YTDSales,
SUM(i.committed_qty) FILTER
(WHERE extract('month' from h.invoice_date) = p.month) as MTDQty,
SUM(i.committed_qty * i.unit_price) FILTER
(WHERE extract('month' from h.invoice_date) = p.month) as MTDSales
FROM params p
CROSS JOIN sales_history h
LEFT JOIN sales_history_items i
ON i.invoice_no = h.invoice_no
WHERE i.part_no is not null
AND h.invoice_date >= p.year
AND h.invoice_date < p.year + interval '1 year'
GROUP BY h.cust_no, i.part_no
If I follow you correctly, you can do conditional aggregation:
select sh.cust_no, shi.part_no,
sum(shi.qty) mtd_qty,
sum(shi.qty * shi.unit_price) ytd_sales,
sum(shi.qty) filter(where sh.invoice_date >= date_trunc('month', current_date) mtd_qty,
sum(shi.qty * shi.unit_price) filter(where sh.invoice_date >= date_trunc('month', current_date) mtd_sales
from sales_history sh
left join sales_history_items shi on sh.invoice_no = shi.invoice_no
where shi.part_no is not null and sh.invoice_date >= date_trunc('year', current_date)
group by sh.cust_no, shi.part_no
The logic is to filter on the current year, and use simple aggregation to compute the "year to date" figures. To get the "month to date" columns, we can just filter the aggregate functions.

How to re-write my T-SQL query to eliminate the "aggregate function on an expression" error?

I am using SQL Server 2014 and I have the following query that is giving me a specific error message: "Cannot perform an aggregate function on an expression containing an aggregate or a subquery".
USE MyDatabase
SELECT [MTH],
[RoomTypeCode],
SUM ([RN] * [AdultCount] / SUM ([RN])) AS 'Weighted Adult Ratio',
SUM ([RN] * [ChildCount] / SUM ([RN])) AS 'Weighted Child Ratio'
FROM PaxRatio
WHERE [PropertyCode] = 'XYZ'
AND [MTH] between '2015-07-01' and '2016-09-30'
The objective of the query is to give me the weighted averages of the AdultCount and ChildCount columns in my View Table (called PaxRatio).
I've tried with a CTE table rather than a VIEW Table but I am still getting the same error!
I think you only have to change the position of the brackets:
SELECT [MTH],
[RoomTypeCode],
SUM ([RN] * [AdultCount]) / SUM ([RN]) AS 'Weighted Adult Ratio',
SUM ([RN] * [ChildCount]) / SUM ([RN]) AS 'Weighted Child Ratio'
FROM PaxRatio
WHERE [PropertyCode] = 'XYZ'
AND [MTH] between '2015-07-01' and '2016-09-30'
You cannot perform a SUM within another SUM function. You can instead calculate the SUM in a separate query and use CROSS JOIN in order to consume the computed value in your main query:
SELECT [MTH],
[RoomTypeCode],
SUM ([RN] * [AdultCount] / sum_rn) AS 'Weighted Adult Ratio',
SUM ([RN] * [ChildCount] / sum_rn) AS 'Weighted Child Ratio'
FROM PaxRatio
CROSS JOIN (
SELECT SUM([RN]) AS sum_rn
FROM PaxRatio
WHERE [PropertyCode] = 'XYZ' AND
[MTH] BETWEEN '2015-07-01' AND '2016-09-30') t
WHERE [PropertyCode] = 'XYZ' AND
[MTH] between '2015-07-01' and '2016-09-30'

SQL Year over year growth percentage from data same query

How do I calculate the percentage difference from 2 different columns, calculated in that same query? Is it even possible?
This is what I have right now:
SELECT
Year(OrderDate) AS [Year],
Count(OrderID) AS TotalOrders,
Sum(Invoice.TotalPrice) AS TotalRevenue
FROM
Invoice
INNER JOIN Order
ON Invoice.InvoiceID = Order.InvoiceID
GROUP BY Year(OrderDate);
Which produces this table
Now I'd like to add one more column with the YoY growth, so even when 2016 comes around, the growth should be there..
EDIT:
I should clarify that I'd like to have for example next to
2015,5,246.28 -> 346,15942029% ((R2015-R2014) / 2014 * 100)
If you save your existing query as qryBase, you can use it as the data source for another query to get what you want:
SELECT
q1.Year,
q1.TotalOrders,
q1.TotalRevenue,
IIf
(
q0.TotalRevenue Is Null,
Null,
((q1.TotalRevenue - q0.TotalRevenue) / q0.TotalRevenue) * 100
) AS YoY_growth
FROM
qryBase AS q1
LEFT JOIN qryBase AS q0
ON q1.Year = (q0.Year + 1);
Access may complain it "can't represent the join expression q1.Year = (q0.Year + 1) in Design View", but you can still edit the query in SQL View and it will work.
What you are looking for is something like this?
Year Revenue Growth
2014 55
2015 246 4.47
2016 350 1.42
You could wrap the original query a twice to get the number from both years.
select orders.year, orders.orders, orders.revenue,
(select (orders.revenue/subOrders.revenue)
from
(
--originalQuery or table link
) subOrders
where subOrders.year = (orders.year-1)
) as lastYear
from
(
--originalQuery or table link
) orders
here's a cheap union'd table example.
select orders.year, orders.orders, orders.revenue,
(select (orders.revenue/subOrders.revenue)
from
(
select 2014 as year, 2 as orders, 55.20 as revenue
union select 2015 as year, 2 as orders, 246.28 as revenue
union select 2016 as year, 7 as orders, 350.47 as revenue
) subOrders
where subOrders.year = (orders.year-1)
) as lastYear
from
(
select 2014 as year, 2 as orders, 55.20 as revenue
union select 2015 as year, 2 as orders, 246.28 as revenue
union select 2016 as year, 7 as orders, 350.47 as revenue
) orders

SQL:Pivot table which includes sum and percentage total

I'm trying to recreate a view in Tableau as a view in SQL. It requires me pivoting a table based on month and not only summing the amount but I also need to sum by margin and also create a Margin % row.The desired output is
BUSINESS_UNIT CLASS JANUARY FEBRUARY MARCH
202 Cost of Sales 100 (null) 60
202 Revenue 200 80 (null)
202 Margin x xx xxx
202 Margin % x% xx% xxx%
I can pivot based on Month but how do perform twos sums in one pivot table and how would I go about including a percenatge row also?
Code so far
SELECT
*
FROM
(SELECT
[Business_Unit]
,[Class]
,Month as Period
,[Amount]
--,Margin
FROM [sample_table]
where [Class] in ('Revenue','Cost of Sales') )AS T
PIVOT(SUM(Amount)
FOR Period IN ([January],[February],[March])) as Pvt
I have included my code so far http://www.sqlfiddle.com/#!3/06bafc/6
Not the prettiest SQL I've done. but this seems to work...
http://www.sqlfiddle.com/#!3/06bafc/60/0
What it does is build on what you've done by generating a margin line and adding a total column
Using this line and total we can then calculate the % of margin. Grouping SETS allowed me to generate the multiple rows, subtotals and totals, Since I knew the only additional line generated would have a null class, I was able to set the Name of the class to margin when null.
WITH CTE AS (
SELECT
Business_Unit
,case when class is NULL then 'Margin' else class end as Class
,Sum(January) as January
,Sum(February) as February
,Sum(March) as march
,Sum(coalesce(January,0)+coalesce(February,0)+coalesce(March,0)) as Total
FROM (
SELECT
*
FROM
(SELECT
[Business_Unit]
,[Class]
,Month as Period
,[Amount]
--,Margin
FROM [sample_table]
where [Class] in ('Revenue','Cost of Sales') )AS T
PIVOT(SUM(Amount)
FOR Period IN ([January],[February],[March])) as Pvt
) as Base
GROUP BY Grouping sets
((Business_Unit,Class,January,February,March,
coalesce(January,0)+coalesce(February,0)+coalesce(March,0))
,(Business_Unit)
))
SELECT *
FROM CTE UNION
SELECT Business_Unit
,'Margin %'
,January*100.00/Total
,February*100.00/Total
,March*100.00/Total
,Total*100.00/Total
FROM CTE
WHERE CLASS='Margin'

How to divide by the result of another query

This is a separate question based on a previous post:
[Link] How to calculate Grand Totals when using OVER (partition by ...) using Oracle SQL
I am using the following Oracle SQL query:
SELECT JOB_GROUP,
SUM(PEOPLE) AS CURRENT_PEOPLE
SUM(PEOPLE) / '100' AS RATIO
FROM MY_VIEW
WHERE MONTH = '01-DEC-2013'
GROUP BY ROLLUP (OB_GROUP)
ORDER BY RATIO DESC;
This query gives me an output like this..
JOB_GROUP CURRENT_PEOPLE RATIO
WORKER1 100 1.0
WORKER2 30 .3
WORKER3 40 .4
WORKER4 25 .25
WORKER5 30 .30
(NULL) 225 2.25
I need to be able to divide the sum of all of the ratios into the sum of the ratios where job_group = 'WORKER1', WORKER2, WORKER4. For Example, we can have 5 different job_groups, but I only need the sum of the ratio for 1, 2 and 4. I suspect this is some type of subquery, but have not been able to get the right result yet.
The equation would look like sum(ratios) / sum(ratio) where worker, 1,2,4. 2.25 / (1.0 + .3 + .25) = .80
Thanks for any help you can provide,
The following uses an analytic function to get the number of worker1s:
select JOB_GROUP, CURRENT_PEOPLE,
CURRENT_PEOPLE / sum(job_group = 'WORKER1' then CURRENT_PEOPLE end) over () as Ratio
from (SELECT JOB_GROUP,
SUM(PEOPLE) AS CURRENT_PEOPLE
FROM my_view
WHERE MONTH = '01-DEC-2013'
GROUP BY ROLLUP (JOB_GROUP)
) t
ORDER BY RATIO DESC;