Summarize the employees by net revenue and not order date? - sql

The sales director would like to reward the employees with net sales over $150,000 for the years 2015 and 2016 combined. The Sales Manager would like the resulting query to display the following columns: Employee ID, Employee Name (First and Last as one field), Total Net Sales per employee. (Both years should be combined into one number.)
Sort largest to smallest.
We cannot figure out how to combine the revenues by the employees.
select o.EmpID, EmpFName + ' ' + EmpLastName as "Employee Name"
, sum((salesunitprice*quantitysold)-((salesunitprice*quantitysold)*ItemDiscount)) as "Net Sales"
from EMPLOYEE e
inner join ORDERS o on e.EmpID = o.EmpID
inner join SALES_INVOICE si on o.OrderID = si.OrderID
inner join SALES_INVOICE_DETAIL sd on si.SalesInvoiceID = sd.SalesInvoiceID
group by o.EmpID, EmpFName + ' ' + EmpLastName, OrderDate
having OrderDate between '2015-01-01' and '2016-12-31'
order by [Employee Name]
I expected the output to be the total per employee, but it is broken out by individual order dates instead of summing the total net sales per employee.

Remove OrderDate from the GROUP BY:
select o.EmpID, EmpFName + ' ' + EmpLastName as "Employee Name",
sum(salesunitprice * quantitysold * (1 - discount)) as "Net Sales"
from EMPLOYEE e join
ORDERS o
on e.EmpID = o.EmpID join
SALES_INVOICE si
on o.OrderID = si.OrderID join
SALES_INVOICE_DETAIL sd
on si.SalesInvoiceID = sd.SalesInvoiceID
where o.OrderDate >= '2015-01-01' and
o.OrderDate < '2017-01-01'
group by o.EmpID, EmpFName + ' ' + EmpLastName
having sum(salesunitprice * quantitysold * (1 - discount)) >= 150000
order by [Employee Name]
Notes:
You want to do the date filtering before the aggregation.
BETWEEN doesn't work with datetimes. The formulation with >= and < works with both dates and datetimes.
I have simplified the arithmetic to calculate net sales.
The important part is removing the extra key in the GROUP BY.
And you want a having clause to filter the net sales.

Related

Joining two queries together into one main table

I have the following two queries that I need to join together to get one final output.
The primary keys are year, month,cost_center, g.account, and e.submapping.
The first table is an acutals table from a GL while the second query is a planned amount. I am trying to compare actuals to plan and need to join these two tables with the primary keys listed.
---Query 1 (e)
with Ranking as (
select c.*, rank() over(partition by
c.ledger_name,
c.company_code,
c.location_code,
c.cost_center,
c.account_number,
c.period_name,
c.currency,
c.amount,
c.entered_amount,
c.dm_insert_dt
order by dw_last_updated DESC) rnk
from wbr_global.gl_ap_details c
where cost_center IN ('1168','1153','1172','1257')
and ledger_name IN ('ABC.com, Inc.')
and account_number between '59999' and '70000')
select
to_date(period_name, 'Mon-YY') as BalanceDate,
date_part(month,(to_date(period_name, 'Mon-YY'))) as Months,
Case
when right(period_name,2) = right(date_part_year(current_date),2) then 'Current Year'
when right(period_name,2) = right(date_part_year(current_date) - 1,2) then 'Prior Year'
else 'Error' end as YearFlag,
EXTRACT(YEAR from balancedate) as year,
EXTRACT(Month from balancedate) as month,
e.sub_mapping,
c.cost_center,
c.period_name,
sum(c.amount) as amount
from Ranking c
left join wbr_global.raw_station_extended_attribute d on c.location_code = d.location_code
left join sandbox.utr_fixed_mapping_na e on c.account_number = e.account_number
where c.cost_center IN ('1168','1153','1172','1257')
and c.ledger_name = 'abc.com, Inc.'
and c.rnk = 1
group by 1,2,3,4,5,6,7,8
limit 10
Here is the second query
---Second query g
EXTRACT(YEAR from first_day_of_month) as year,
EXTRACT(Month from first_day_of_month) as month,
first_day_of_month,country,cost_center,scenario,'employee_relation' as account,
sum(employee_relation) as amount
from prophecy_to_sabre_ds_db.prophecy_caffeine.output_ww_field_opex
where cost_center = 1172
AND scenario = 'Q2G_22_1'
group by 1,2,3,4,5,6
Would I be able to make one a sub query in the other and join that way.
(Query 2) as g on g.cost_center = c.cost_center
and g.account = e.sub_mapping
and g.year = e.year
and g.month = e.month

Where clause within Case Statement

I need to drill into detail on to an existing report which shows me the total profitability per customer, per month on a telecoms company.
The company sells calls, service charges and has discounts.
This is the query that I'm using, using one customer in particular:
SELECT
custumer_name,
ISNULL(SUM(CASE CONVERT(VARCHAR(10), month_end, 103)
WHEN '31/10/2016'
THEN totcall + isnull(totrec, 0) - discount
ELSE 0
END), 0) AS '31/10/2016',
SUM(totcall) AS 'Total Calls',
SUM(totrec) AS 'Total Rec',
SUM(discount) AS 'Discounts'
FROM
total_sales
INNER JOIN
customer_details ON billingaddress = customer_details .siteid
INNER JOIN
sales_month d ON total_sales.periodid = d.monthid
INNER JOIN
customer b ON customer_details .id = b.id AND b.is_customer = 1
WHERE
b.custumer_name = '2
GROUP BY
b.custumer_name
ORDER BY
b.custumer_name ASC
This is bringing back the correct total however when I need to show the drilldown of the total on calls, rec & discounts it is showing me the actual sum of every months' data which is stored on that table.
I'm not sure how can I get the last 3 columns to itemise the total without specifying the actual month (as the report has columns for the last 12 months of data.
Please help?
Thank you!
PS. The DB is a SQL Server 2008

How to get the discount number of customers in prior period?

I have a requirement where I supposed to roll customer data in the prior period of 365 days.
Table:
CREATE TABLE orders (
persistent_key_str character varying,
ord_id character varying(50),
ord_submitted_date date,
item_sku_id character varying(50),
item_extended_actual_price_amt numeric(18,2)
);
Sample data:
INSERT INTO orders VALUES
('01120736182','ORD6266073' ,'2010-12-08','100856-01',39.90),
('01120736182','ORD33997609' ,'2011-11-23','100265-01',49.99),
('01120736182','ORD33997609' ,'2011-11-23','200020-01',29.99),
('01120736182','ORD33997609' ,'2011-11-23','100817-01',44.99),
('01120736182','ORD89267964' ,'2012-12-05','200251-01',79.99),
('01120736182','ORD89267964' ,'2012-12-05','200269-01',59.99),
('01011679971','ORD89332495' ,'2012-12-05','200102-01',169.99),
('01120736182','ORD89267964' ,'2012-12-05','100907-01',89.99),
('01120736182','ORD89267964' ,'2012-12-05','200840-01',129.99),
('01120736182','ORD125155068','2013-07-27','201443-01',199.99),
('01120736182','ORD167230815','2014-06-05','200141-01',59.99),
('01011679971','ORD174927624','2014-08-16','201395-01',89.99),
('01000217334','ORD92524479' ,'2012-12-20','200021-01',29.99),
('01000217334','ORD95698491' ,'2013-01-08','200021-01',19.99),
('01000217334','ORD90683621' ,'2012-12-12','200021-01',29.990),
('01000217334','ORD92524479' ,'2012-12-20','200560-01',29.99),
('01000217334','ORD145035525','2013-12-09','200972-01',49.99),
('01000217334','ORD145035525','2013-12-09','100436-01',39.99),
('01000217334','ORD90683374' ,'2012-12-12','200284-01',39.99),
('01000217334','ORD139437285','2013-11-07','201794-01',134.99),
('01000827006','W02238550001','2010-06-11','HL 101077',349.000),
('01000827006','W01738200001','2009-12-10','EL 100310 BLK',119.96),
('01000954259','P00444170001','2009-12-03','PC 100455 BRN',389.99),
('01002319116','W02242430001','2010-06-12','TR 100966',35.99),
('01002319116','W02242430002','2010-06-12','EL 100985',99.99),
('01002319116','P00532470001','2010-05-04','HO 100482',49.99);
Using the query below I am trying to get the number of distinct customers by order_submitted_date:
select
g.order_date as "Ordered",
count(distinct o.persistent_key_str) as "customers"
from
generate_series(
(select min(ord_submitted_date) from orders),
(select max(ord_submitted_date) from orders),
'1 day'
) g (order_date)
left join
orders o on o.ord_submitted_date between g.order_date - interval '364 days'
and g.order_date
WHERE extract(year from ord_submitted_date) <= 2009
group by 1
order by 1
This is the output I expected.
Ordered Customers
2009-12-03 1
2009-12-10 1
When I execute the query above I get incorrect results.
How can I make this right?
To get your expected output ("the number of distinct customers") - only days with actual orders 2009:
SELECT ord_submitted_date, count(DISTINCT persistent_key_str) AS customers
FROM orders
WHERE ord_submitted_date >= '2009-1-1'
AND ord_submitted_date < '2010-1-1'
GROUP BY 1
ORDER BY 1;
Formulate the WHERE conditions this way to make the query sargable, and input easy.
If you want one row per day (from the earliest entry up to the latest in orders) - within 2009:
SELECT ord_submitted_date AS ordered
, count(DISTINCT o.persistent_key_str) AS customers
FROM (SELECT generate_series(min(ord_submitted_date) -- single query ...
, max(ord_submitted_date) -- ... to get min / max
, '1d')::date FROM orders) g (ord_submitted_date)
LEFT join orders o USING (ord_submitted_date)
WHERE ord_submitted_date >= '2009-1-1'
AND ord_submitted_date < '2010-1-1'
GROUP BY 1
ORDER BY 1;
SQL Fiddle.
Distinct customers per year
SELECT extract(year from ord_submitted_date) AS year
, count(DISTINCT persistent_key_str) AS customers
FROM orders
GROUP BY 1
ORDER BY 1;
SQL Fiddle.

Sql Sum Multiplying Results

I've trying to convert this same into a "Gross Profit" type report and am running into an issue.
select
CONVERT(VARCHAR(12), ih.invoice_date,110) as invoice_date,
oh.order_no,
bosr.salesrep_name,
bosr.salesrep_id,
oh.location_id,
oh.taker,
oh.customer_id,
Replace(oh.ship2_name, ',', ' ') as Ship_to_name,
bosr.supplier_id,
Replace(bosr.supplier_name, ',', ' ') as Supplier_name,
Cast((dc.dealer_commission_amt_due) as DECIMAL (19,2)) as "Gross Profit"
from oe_hdr oh
inner join anspin_view_booked_orders_ship_to_rep bosr
on oh.order_no = bosr.order_no
inner join oe_line ol
on oh.order_no = ol.order_no
inner join invoice_hdr ih
on oh.order_no = ih.order_no
inner join dealer_commission dc
on ih.invoice_no = dc.invoice_no
where
ih.invoice_date >= '2014-07-01' and
ih.invoice_date < '2014-08-01' and
ol.qty_ordered > '0' and
bosr.source_code_no <> '706' and
bosr.source_code_no <> '709'
group by
CONVERT(VARCHAR(12), ih.invoice_date, 110),
oh.order_no,
bosr.salesrep_name,
bosr.salesrep_id,
oh.location_id,
oh.customer_id,
oh.taker,
oh.ship2_name,
bosr.supplier_id,
bosr.supplier_name,
dc.dealer_commission_amt_due
order by invoice_date;
This worked great and the "Gross Profit" column is showing the correct values in the date range I want...now if I were to remove the "dc.dealer_commission_amt_due" from the group by, and then make this change:
Cast(sum(dc.dealer_commission_amt_due) as DECIMAL (19,2)) as "Gross Profit"
I get amounts in SOME (Not all! Which is weird since some are correct) of the invoice numbers as 2-4+ times their original value.
Example Between the two:
invoice_date order_no salesrep_name salesrep_id location_id taker customer_id Ship_to_name supplier_id Supplier_name Gross Profit
07-10-2014 X NAME ID 60 NAME X Customer INC 123452 supplier INC. 4800.00
Non-Sum:
invoice_date order_no salesrep_name salesrep_id location_id taker customer_id Ship_to_name supplier_id Supplier_name Gross Profit
07-10-2014 X NAME ID 60 NAME X Customer INC 123452 supplier INC. 750.00
invoice_date order_no salesrep_name salesrep_id location_id taker customer_id Ship_to_name supplier_id Supplier_name Gross Profit
07-10-2014 X NAME ID 60 NAME X Customer INC 123452 supplier INC. 450.00
From what I've read this has to do with the joins...is this correct?
These two queries are not the same:
SELECT Cast(( dc.dealer_commission_amt_due ) AS DECIMAL (19, 2)) AS "Gross Profit"
FROM dealer_commission dc
GROUP BY dc.dealer_commission_amt_due
SELECT Cast(( SUM(dc.dealer_commission_amt_due) ) AS DECIMAL (19, 2)) AS "Gross Profit"
FROM dealer_commission dc
Adding additional columns in your GROUP BY clause will return more rows in the result, but it should not effect the sum. Removing a column in the GROUP BY will return less rows and again should not effect the sum.
The only part of the query that can effect the sum is which rows are matched.
Also, keep in mind the order of operations of a query:
FROM
WHERE
GROUP BY
HAVING
SELECT
ORDER BY
Do you need an aggregation?
select
CONVERT(VARCHAR(12), ih.invoice_date,110) as invoice_date,
oh.order_no,
bosr.salesrep_name,
bosr.salesrep_id,
oh.location_id,
oh.taker,
oh.customer_id,
Replace(oh.ship2_name, ',', ' ') as Ship_to_name,
bosr.supplier_id,
Replace(bosr.supplier_name, ',', ' ') as Supplier_name,
SUM(Cast((dc.dealer_commission_amt_due) as DECIMAL (19,2))) as "Gross Profit" --<<AGGREGATION ADDED
from oe_hdr oh
inner join anspin_view_booked_orders_ship_to_rep bosr
on oh.order_no = bosr.order_no
inner join oe_line ol
on oh.order_no = ol.order_no
inner join invoice_hdr ih
on oh.order_no = ih.order_no
inner join dealer_commission dc
on ih.invoice_no = dc.invoice_no
where
ih.invoice_date >= '2014-07-01' and
ih.invoice_date < '2014-08-01' and
ol.qty_ordered > '0' and
bosr.source_code_no <> '706' and
bosr.source_code_no <> '709'
group by
CONVERT(VARCHAR(12), ih.invoice_date, 110),
oh.order_no,
bosr.salesrep_name,
bosr.salesrep_id,
oh.location_id,
oh.customer_id,
oh.taker,
oh.ship2_name,
bosr.supplier_id,
bosr.supplier_name
order by invoice_date;
Ended up having to pay for the software company to write a query since they have the "encyclopedia" on linking the different tables together.
I was able to get 50% there by getting rid of the multiplication on my own, but only 50% of the order types were showing up...I gave up and now have a working query that I can compare against.
Thanks for all your help and suggestions!

MySQL: Returning multiple columns from an in-line subquery

I'm creating an SQL statement that will return a month by month summary on sales.
The summary will list some simple columns for the date, total number of sales and the total value of sales.
However, in addition to these columns, i'd like to include 3 more that will list the months best customer by amount spent. For these columns, I need some kind of inline subquery that can return their ID, Name and the Amount they spent.
My current effort uses an inline SELECT statement, however, from my knowledge on how to implement these, you can only return one column and row per in-line statement.
To get around this with my scenario, I can of course create 3 separate in-line statements, however, besides this seeming impractical, it increases the query time more that necessary.
SELECT
DATE_FORMAT(OrderDate,'%M %Y') AS OrderMonth,
COUNT(OrderID) AS TotalOrders,
SUM(OrderTotal) AS TotalAmount,
(SELECT SUM(OrderTotal) FROM Orders WHERE DATE_FORMAT(OrderDate,'%M %Y') = OrderMonth GROUP BY OrderCustomerFK ORDER BY SUM(OrderTotal) DESC LIMIT 1) AS TotalCustomerAmount,
(SELECT OrderCustomerFK FROM Orders WHERE DATE_FORMAT(OrderDate,'%M %Y') = OrderMonth GROUP BY OrderCustomerFK ORDER BY SUM(OrderTotal) DESC LIMIT 1) AS CustomerID,
(SELECT CustomerName FROM Orders INNER JOIN Customers ON OrderCustomerFK = CustomerID WHERE DATE_FORMAT(OrderDate,'%M %Y') = OrderMonth GROUP BY OrderCustomerFK ORDER BY SUM(OrderTotal) DESC LIMIT 1) AS CustomerName
FROM Orders
GROUP BY DATE_FORMAT(OrderDate,'%m%y')
ORDER BY DATE_FORMAT(OrderDate,'%y%m') DESC
How can i better structure this query?
FULL ANSWER
After some tweaking of Dave Barkers solution, I have a final version for anyone in the future looking for help.
The solution by Dave Barker worked perfectly with the customer details, however, it made the simpler Total Sales and Total Sale Amount columns get some crazy figures.
SELECT
Y.OrderMonth, Y.TotalOrders, Y.TotalAmount,
Z.OrdCustFK, Z.CustCompany, Z.CustOrdTotal, Z.CustSalesTotal
FROM
(SELECT
OrdDate,
DATE_FORMAT(OrdDate,'%M %Y') AS OrderMonth,
COUNT(OrderID) AS TotalOrders,
SUM(OrdGrandTotal) AS TotalAmount
FROM Orders
WHERE OrdConfirmed = 1
GROUP BY DATE_FORMAT(OrdDate,'%m%y')
ORDER BY DATE_FORMAT(OrdDate,'%Y%m') DESC)
Y INNER JOIN
(SELECT
DATE_FORMAT(OrdDate,'%M %Y') AS CustMonth,
OrdCustFK,
CustCompany,
COUNT(OrderID) AS CustOrdTotal,
SUM(OrdGrandTotal) AS CustSalesTotal
FROM Orders INNER JOIN CustomerDetails ON OrdCustFK = CustomerID
WHERE OrdConfirmed = 1
GROUP BY DATE_FORMAT(OrdDate,'%m%y'), OrdCustFK
ORDER BY SUM(OrdGrandTotal) DESC)
Z ON Z.CustMonth = Y.OrderMonth
GROUP BY DATE_FORMAT(OrdDate,'%Y%m')
ORDER BY DATE_FORMAT(OrdDate,'%Y%m') DESC
Move the inline SQL to be a inner join query. So you'd have something like...
SELECT DATE_FORMAT(OrderDate,'%M %Y') AS OrderMonth, COUNT(OrderID) AS TotalOrders, SUM(OrderTotal) AS TotalAmount, Z.OrderCustomerFK, Z.CustomerName, z.OrderTotal as CustomerTotal
FROM Orders
INNER JOIN (SELECT DATE_FORMAT(OrderDate,'%M %Y') as Mon, OrderCustomerFK, CustomerName, SUM(OrderTotal) as OrderTotal
FROM Orders
GROUP BY DATE_FORMAT(OrderDate,'%M %Y'), OrderCustomerFK, CustomerName ORDER BY SUM(OrderTotal) DESC LIMIT 1) Z
ON Z.Mon = DATE_FORMAT(OrderDate,'%M %Y')
GROUP BY DATE_FORMAT(OrderDate,'%m%y'), Z.OrderCustomerFK, Z.CustomerName
ORDER BY DATE_FORMAT(OrderDate,'%y%m') DESC
You can also do something like:
SELECT
a.`y`,
( SELECT #c:=NULL ) AS `temp`,
( SELECT #d:=NULL ) AS `temp`,
( SELECT
CONCAT(#c:=b.`c`, #d:=b.`d`)
FROM `b`
ORDER BY b.`uid`
LIMIT 1 ) AS `temp`,
#c as c,
#d as d
FROM `a`
Give this a shot:
SELECT CONCAT(o.order_month, ' ', o.order_year),
o.total_orders,
o.total_amount,
x.sum_order_total,
x.ordercustomerfk,
x.customername
FROM (SELECT MONTH(t.orderdate) AS order_month,
YEAR(t.orderdate) AS order_year
COUNT(t.orderid) AS total_orders,
SUM(t.ordertotal) AS total_amount
FROM ORDERS t
GROUP BY MONTH(t.orderdate), YEAR(t.orderdate)) o
JOIN (SELECT MONTH(t.orderdate) AS ordermonth,
YEAR(t.orderdate) AS orderyear
SUM(t.ordertotal) 'sum_order_total',
t.ordercustomerfk,
c.customername
FROM ORDERS t
JOIN CUSTOMERS c ON c.customerid = o.ordercustomerfk
GROUP BY t.ordercustomerfk, MONTH(t.orderdate), YEAR(t.orderdate)) x ON x.order_month = o.order_month
AND x.order_year = o.order_year
ORDER BY o.order_year DESC, o.order_month DESC