calculating transaction amount for the following week - google-bigquery

Transaction -> Transaction_id, buyer_id, seller_id, object_id,Shipping_id, Price, Quantity, site_id,transaction_date, expected_delivery_date, check_out_status
leaf_category_id, defect_id
Buyer -> Buyer_id, name, country
Seller -> Seller_id, name, country, segment, standard
Listing -> object_id, seller_id, auction_start_date
auction_end_date, listing_site_id, leaf_category_id
quantity
For the sellers from UK who transacted on the second week of december(6 December 2015 to 12 December 2015), find the number of sellers
who have atleast twice the total transaction amount (qty*price) in the following week.
I have tried below query to get sellers who transacted in dec 2nd week but facing error when calculating sellers having twice the transaction amount from those sellers in following week.
With trans_dec_uk as
(
select s.seller_id,t.transaction_date, sum(t.Qty * Price) trans_amount
from transaction t join seller s
on t.seller_id =s.seller_id
where s.country ='UK'
and t.transaction_date between '12-05-2015' and '12-18-2015'
group by s.seller_id,t.transaction_date
)
select count(seller) from  trans_dec_uk
where trans_amount =  2 * to_char(sysdate+7,'DD-MM')

with uk_sellers as (
select * from <dataset>.Seller where country = 'UK'
),
first_week_uk as (
select seller_id, sum(Price*Quantity) as first_week_total
from <dataset>.Transaction
inner join uk_sellers using(seller_id)
where transaction_date between '2015-12-05' and '2015-12-11'
group by 1
),
second_week_uk as (
select seller_id, sum(Price*Quantity) as second_week_total
from <dataset>.Transaction
inner join uk_sellers using(seller_id)
where transaction_date between '2015-12-12' and '2015-12-18'
group by 1
)
select count(distinct seller_id) as the_answer
from first_week_uk
inner join second_week_uk using(seller_id)
where second_week_total >= 2*first_week_total

Related

Combining multiple queries

I want a table with all customers and their last charge transaction date and their last invoice date. I have the first two, but don't know how to add the last invoice date to the table. Here's what I have so far:
WITH
--Last customer transaction
cust_trans AS (
SELECT customer_id, created
FROM charges a
WHERE created = (
SELECT MAX(created) AS last_trans
FROM charges b
WHERE a.customer_id = b.customer_id)),
--All customers
all_cust AS (
SELECT customers.id AS customer, customers.email, CAST(customers.created AS DATE) AS join_date, ((1.0 * customers.account_balance)/100) AS balance
FROM customers),
--Last customer invoice
cust_inv AS (
SELECT customer_id, date
FROM invoices a
WHERE date = (
SELECT MAX(date) AS last_inv
FROM invoices b
WHERE a.customer_id = b.customer_id))
SELECT * FROM cust_trans
RIGHT JOIN all_cust ON all_cust.customer = cust_trans.customer_id
ORDER BY join_date;
This should get what you need. Notice each individual subquery is left-joined to the customer table, so you always START with the customer, and IF there is a corresponding record in each subquery for max charge date or max invoice date, it will be pulled in. Now, you may want to apply a COALESCE() for the max dates to prevent showing nulls, such as
COALESCE(maxCharges.LastChargeDate, '') AS LastChargeDate
but your call.
SELECT
c.id AS customer,
c.email,
CAST(c.created AS DATE) AS join_date,
((1.0 * c.account_balance) / 100) AS balance,
maxCharges.LastChargeDate,
maxInvoices.LastInvoiceDate
FROM
customers c
LEFT JOIN
(SELECT
customer_id,
MAX(created) LastChargeDate
FROM
charges
GROUP BY
customer_id) maxCharges ON c.id = maxCharges.customer_id
LEFT JOIN
(SELECT
customer_id,
MAX(date) LastInvoiceDate
FROM
invoices
GROUP BY
customer_id) maxInvoices ON c.id = maxInvoices.customer_id
ORDER BY
c.created

Averaging and Grouping In google Big Query

I have the table as shown in google big Query:
I just want to do the following:
Calculate Category wise total units sold
Calculate Category wise average selling price
consider below approach
select 'category' type, category name, count(1) units_sold, sum(sale_price) total_sale, round(avg(sale_price), 2) average_selling_price
from your_table group by category
union all
select * from (
select 'product' type, product name, count(1) units_sold, sum(sale_price) total_sale, round(avg(sale_price), 2) average_selling_price
from your_table group by product
order by total_sale desc limit 10
)
union all
select * from (
select 'order_date' type, '' || order_date name, count(1) units_sold, sum(sale_price) total_sale, round(avg(sale_price), 2) average_selling_price
from your_table group by order_date
order by total_sale desc limit 5
)
order by type
if applied to sample/dummy data - output would be like below

SQL: Looking at Bundle of Products Sold

I have a sample DB below. I'm looking to see how many TV and Internet bundles we sold. In the sample data, only Bob and Trevor sold that bundle so we sold 2.
How do I write the query for the number of bundles sold by each Sales rep and the total price of the bundles sold?
Thanks
I imagine that, for a bundle to happen, the same sales person needs to have sold both products to the same customer.
I would approach this with two levels of aggregation. First group by sales person and customer in a subquery to identify the bundles, then, in an outer query, count how many such bundles happened for each sales person:
SELECT sales_person, COUNT(*) bundles_sold, SUM(total_price) total_price
FROM (
SELECT sales_person, customer_name, SUM(total_price) total_price
FROM mytable
WHERE product_name in ('TV', 'Phone')
GROUP BY sales_person
HAVING COUNT(DISTINCT product_name) = 2
) x
You can simply group the salesman's by counting the distinct products they sold -
SELECT Sales_Person, FLOOR(COUNT(DISTINCT product_name)/2) NO_OF_BUNDLES, sum(total_price)
FROM YOUR_TAB
WHERE product_name IN ('TV', 'Internet')
GROUP BY Sales_Person
HAVING COUNT(DISTINCT product_name) >= 2
Using cte as below:
with cte1(sales_person, customer_name, product_count) as
(
select sales_person, customer_name, count(product_name)
from sales
where product_name in ('TV', 'Internet')
group by sales_person, customer_name
having count(product_name) = 2
)
select sales_person, count(product_count)
from cte1
group by sales_person
I would suggest two levels of aggregation:
select sales_person, count(*), sum(total_price)
from (select sales_person, customer_name,
sum(total_price) as total_price,
max(case when product_name = 'tv' then 1 else 0 end) as has_tv,
max(case when product_name = 'phone' then 1 else 0 end) as has_phone,
max(case when product_name = 'internet' then 1 else 0 end) as has_internet
from t
group by sales_person, customer_name
) sc
where has_phone = 0 and
has_tv = 1 and
has_internet = 1
group by sales_person;
I recommend this structure because it is pretty easy to change the conditions in the where clause to return this for any bundle -- or even to aggregate by the three flags and return the totals for all bundles in one query.

Decile analysis - customer and revenue and vice versa

I am trying to produce an analysis which shows 2 things.
Deciles (or percentiles) of customers and their revenue so I can see what 10% of customer count produce the the most revenue.
Deciles of Revenue : how many customers produce 10% of revenue.
select yeardate, decile, sum(revenue) as revenue, count(distinct(customername)) as cust_count
from
(
select yeardate,
customername,
ntile(10) over (order by sum(revenue) ) as decile,
sum(revenue) as revenue
from
(select
year(DateStamp) as yeardate ,
customername,
sum(Sell) as revenue
from MarginListView
where reporttype = 'Invoice' and sell >0 and year(datestamp) = 2018
group by year(DateStamp), customername) d
group by yeardate, CustomerName) c
group by yeardate, decile
order by 1,2
I can get the customer count deciles but not the revenue deciles....
using MS SQL server - Any help appreciated.
To get the number of customers that produce 10% of revenue, start with the cumulative revenue:
select customername, sum(sell) as revenue,
sum(sum(sell)) over (order by sum(sell) desc) as running_revenue
from MarginListView
where reporttype = 'Invoice' and sell > 0 and
year(datestamp) = 2018
group by customername;
To get the number that account for 10%:
select count(*)
from (select customername, sum(sell) as revenue,
sum(sum(sell)) over (order by sum(sell) desc) as running_revenue,
sum(sum(sell)) over () as total_revenue
from MarginListView
where reporttype = 'Invoice' and sell > 0 and
year(datestamp) = 2018
group by customername
) c
where running_revenue - revenue >= 0.1 * total_revenue;
Gordon - thanks for your help.... it really did get me towards where I needed to be.
I ended with this...
select
yeardate, customername,
sell,
cast((round(sum(sum(revenue_sub_tot)) over (order by sum(revenue_sub_tot) asc),2,2)) as decimal (2,2)) as revenue_percentiles,
cast((round(sum(sum(revenue_sub_tot)) over (order by sum(revenue_sub_tot) asc),1,1)) as decimal (2,2)) as revenue_deciles
from (select year(datestamp) as yeardate,
customername,
sum(sell) as sell,
sum(sell)/sum(sum(sell)) over () as revenue_sub_tot
from MarginListView
where reporttype = 'Invoice' and sell > 0
group by year(datestamp), customername
) c
group by yeardate, customername, sell
order by 1,3

How to return the most ordered item for each month

I am trying to return the most ordered product per month, of the year 2007. I would like to see the name of the product, how many of them where ordered that month, and the month. I am using the AdventureWorks2012 database. I have tried a few different ways but each time multiple product orders are returned for the same month, instead of the one product that had the most order quantity that month. Sorry if this is not clear. I am trying to test myself so I make up my own questions and try to answer them. If anyone knows a site that have questions and answers like this so I can verify that would be super helpful! Thanks for any help. Here is the farthest I have been able to get with the query.
WITH Ord2007Sum
AS (SELECT sum(od.orderqty) AS sorder,
od.productid,
oh.orderdate,
od.SalesOrderID
FROM Sales.SalesOrderDetail AS od
INNER JOIN
sales.SalesOrderHeader AS oh
ON od.SalesOrderID = oh.SalesOrderID
WHERE year(oh.OrderDate) = 2007
GROUP BY ProductID, oh.OrderDate, od.SalesOrderID)
SELECT max(sorder),
s.productid,
month(h.orderdate) AS morder --, s.salesorderid
FROM Ord2007Sum AS s
INNER JOIN
sales.SalesOrderheader AS h
ON s.OrderDate = h.OrderDate
GROUP BY s.ProductID, month(h.orderdate)
ORDER BY morder;
Make a CTE that groups our products by month and creates a sum
;WITH OrderRows AS
(
SELECT
od.ProductId,
MONTH(oh.OrderDate) SalesMonth,
SUM(od.orderqty) OVER (PARTITION BY od.ProductId, MONTH(oh.OrderDate) ORDER BY oh.OrderDate) ProdMonthSum
FROM SalesOrderDetail AS od
INNER JOIN SalesOrderHeader AS oh
ON od.SalesOrderID = oh.SalesOrderID
WHERE year(oh.OrderDate) = 2007
),
Make a simple numbers table to break out each month of the year
Months AS
(
SELECT 1 AS MonthNum UNION SELECT 2 UNION SELECT 3 UNION SELECT 4
UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8
UNION SELECT 9 UNION SELECT 10 UNION SELECT 11 UNION SELECT 12
)
We query our months table against the data and select the top product for each month based on the sum
SELECT
m.MonthNum,
d.ProductID,
d.ProdMonthSum
FROM Months m
OUTER APPLY
(
SELECT TOP 1 r.ProductID, r.ProdMonthSum
FROM OrderRows r
WHERE r.SalesMonth = m.MonthNum
ORDER BY ProdMonthSum DESC
) d
Your group by statement should not include oh.OrderDate, od.SalesOrderID because this will aggregate your data to the incorrect level. You want the ProductID that was most commonly sold per month so the group by conditions become ProductID, datepart(mm,oh.OrderDate). As Andrew suggested the Row_Number function is useful in this case as it lets you create a key that is ordered by month and sorder and which resets each month. Finally in the outer query limits the results to the first instance (which is the highest quantity)for each month.
WITH Ord2007Sum
AS(
SELECT sum(od.orderqty) AS sorder,
od.productid,
datepart(mm,oh.OrderDate) AS 'Month'
row_number() over (partition by datepart(mm,oh.OrderDate)
Order by datepart(mm,oh.OrderDate)desc, sorder desc) row
FROM Sales.SalesOrderDetail AS od
INNER JOIN
sales.SalesOrderHeader AS oh
ON od.SalesOrderID = oh.SalesOrderID
WHERE datepart(yyyy,oh.OrderDate) = 2007
GROUP BY ProductID, datepart(mm,oh.OrderDate)
)
SELECT productid,
sorder,
[month]
FROM Ord2007Sum
WHERE row =1