AdventureWorks2012: For each customer, determine the number of orders created in year 2007. Show 0 for no order of that customer. - sql-server-2012-express

AdventureWorks2012: Sql For each customer, determine the number of orders created in year 2007. If a customer has not created any order in year 2004, show 0 for that customer. Show: customer ID, # of orders created in 2007.

Same approach as in my other response - use a CTE (Common Table Expression) to determine number of sales for each customer in the year 2007:
-- determine the number and total of all sales in 2007
;WITH SalesPerCustomer AS
(
SELECT
c.CustomerID,
NumberOfSales = ISNULL(COUNT(soh.SalesOrderID), 0)
FROM
Sales.Customer c
INNER JOIN
Sales.SalesOrderHeader soh ON soh.CustomerID = c.CustomerID
AND soh.OrderDate >= '20070101'
AND soh.OrderDate < '20080101'
GROUP BY
c.CustomerID
)
SELECT
CustomerID ,
NumberOfSales
FROM
SalesPerCustomer
ORDER BY
NumberOfSales DESC
Ordered the output by number of sales descending, so you'll get the customer with the most sales first

Related

TSQL to get latest invoice & invoice date for customers

I'm trying to figure out how I can list out the most recent invoice date & invoice number for my customers. I have the basic structure as follows but can't figure out how to get this data. The two tables use the customer_id as the relationship
SELECT
c.customer_id
c.customer_name
( ? get most recent invoice number)
(?get most recent invoice date)
FROM
customer AS c
JOIN invoice as i on i.customer_id=c.customer_id
There are 2 common methods you can use. Common Table Expression (CTE) to rank all rows per customer_id order by invoice_date descending, and then you pick up date and number of the row ranked #1, or using CROSS APPLY to pick TOP 1 invoice per customer_id again, order by invoice_date descending.
Something like this
-- method #1 using CTE
;WITH cte AS (
SELECT
c.customer_id,
c.customer_name,
i.invoice_number,
i.invoce_date,
ROW_NUMBER() OVER (PARTITION BY c.Customer_id ORDER BY i.invoce_date DESC) rn
FROM
CUSTOMER c
INNER JOIN invoice i on i.customer_id=c.customer_id
)
SELECT cte.customer_id,
cte.customer_name,
cte.invoice_number,
cte.invoice_date
FROM cte
WHERE rm = 1
-- method #2 using CROSS APPLY
SELECT
c.customer_id,
c.customer_name,
ca.invoice_number,
ca.invoice_date
FROM
customer c
CROSS APPLY (
SELECT TOP 1 invoice_number, invoice_date
FROM invoice as i WHERE i.customer_id=c.customer_id
ORDER BY invoice_date DESC
) ca
Your requirement to list out the most recent invoice date & invoice number per each customer could be translated to: for each customer, retrieve the invoice record that there is not exists other invoice of the same customer which has more recent invoice date. The corresponding query should be:
SELECT
c.customer_id,
c.customer_name,
i.invoice_number,
i.invoice_date
FROM
customer c
INNER JOIN invoice i ON i.customer_id = c.customer_id
WHERE NOT EXISTS
(SELECT 1
FROM invoice i1
WHERE i1.invoice_number <> i.invoice_number
AND i1.customer_id = i.customer_id
AND i1.invoice_date > i.invoice_date)

subquery problem - need to get avg of a sum

I have 2 tables
sales table
weekly sales, store, date
store table
store, type, size
my sales table has multiple years, multiple stores and multiple types. I'm trying to get the avg sales by sqft for each store type per year. I have a sub query that shows the sales by sqft for each store but Im having trouble then rolling it up into my main query to get the avg by type
Anything jumps out with my final query?
SELECT
date_part('year', sales.date) AS year,
stores.type,
AVG(sales_by_sqft)
FROM
(SELECT
SUM((sales.weekly_sales)/stores.size) AS sales_by_sqft
FROM SALES
INNER JOIN stores ON sales.store = stores.store
GROUP BY sales.store) AS sq
FROM sales
INNER JOIN stores ON sales.store = stores.store
WHERE date_part('year', date) = 2012
GROUP BY year, stores.type;
getting a syntax error on the second FROM statement
I figured it out. AVG doesn't work on money. Once I changed that data type to integer, it all fell in place
SELECT
year,
type,
ROUND(AVG(sales_by_sqft),2)AS avg_sales_by_sqft
FROM
(SELECT
date_part('year', sales.date) AS year,
stores.type,
sales.store,
stores.size,
SUM(sales.weekly_sales) AS total_sales,
SUM(sales.weekly_sales)/ AVG(stores.size) AS sales_by_sqft
FROM sales
INNER JOIN stores ON sales.store = stores.store
GROUP BY year, stores.type, sales.store, stores.size) AS sq
GROUP BY 1,2
ORDER BY 1,3 DESC;

How can I make the denominator a constant for each of the numbers in the same row in SQL?

I am trying to create a table with the average amount of sales divided by a cohort of users that signed up for an account in a certain month, however, I can only figure out to divide by the number of people that made a purchase in that specific month which is lower than the total amount of the cohort. How do I change the query below to make each of the avg_sucessful_transacted amounts divide by cohort 0 for each month?
thank you.
select sum (t.amount_in_dollars)/ count (distinct u.id) as Avg_Successful_Transacted, (datediff(month,[u.created:month],[t.createdon:month])) as Cohort, [u.created:month] as Months,
count (distinct u.id) as Users
from [transaction_cache as t]
left join [user_cache as u] on t.owner = u.id
where t.type = 'savings' and t.status = 'successful' and [u.created:year] > ['2017-01-01':date:year]
group by cohort, months
order by Cohort, Months
You will need to break out the cohort sizing into its own subquery or CTE in order to calculate the total number of distinct users who were created during the month which matches the cohort's basis month.
I approached this by bucketing users by the month they were created using the date_trunc('Month', <date>, <date>) function, but you may wish to approach it differently based on the specific business logic that generates your cohorts.
I don't work with Periscope, so the example query below is structured for pure Redshift, but hopefully it is easy to translate the syntax into Periscope's expected format:
WITH cohort_sizes AS (
SELECT date_trunc('Month', created)::DATE AS cohort_month
, COUNT(DISTINCT(id)) AS cohort_size
FROM user_cache u
GROUP BY 1
),
cohort_transactions AS (
SELECT date_trunc('Month', created)::DATE AS cohort_month
, createdon
, owner
, type
, status
, amount_in_dollars
, id
, created
FROM transaction_cache t
LEFT JOIN user_cache u ON t.owner = u.id
WHERE t.type = 'savings'
AND t.status = 'successful'
AND u.created > '2017-01-01'
)
SELECT SUM(t.amount_in_dollars) / s.cohort_size AS Avg_Successful_Transacted
, (datediff(MONTH, u.created, t.createdon)) AS Cohort
, u.created AS Months
, count(DISTINCT u.id) AS Users
FROM cohort_transactions t
JOIN cohort_sizes s ON t.cohort_month = s.cohort_month
LEFT JOIN user_cache AS u ON t.owner = u.id
GROUP BY s.cohort_size, Cohort, Months
ORDER BY Cohort, Months
;

Join and aggregate on two columns - for every month even months with no data?

Using SQL Server 2005.
I have a table with calendar months
Month, fiscalorder
june,1
july,2
..
may,12
And another table with employees and a repeating monthly amount
employee, month, amount
john, july, 10
john, july, 3
john, august,2
mary, june, 2
mary, feb, 5
I need to join and aggregate these by month, but every month (even months without data) to report for every employe, but employee then fiscal order.
Output:
june, john, 0
july, john, 13
august,john,2
sept, john, 0
..
june,mary,2
Assuming Sql Server 2005+
Declare #CalenderMonths Table ([Month] Varchar(20),FiscalOrder Int)
Insert Into #CalenderMonths Values
('June',1),('July',2),('August',3),('September',4),('October',5),('November',6),
('December',7),('January',8),('February',9),('March',10),('April',11),('May', 12)
Declare #Employee Table(employee varchar(50), [month] Varchar(20), amount int )
Insert Into #Employee Values('john', 'July', 10),('john', 'July',3),('john','August',2),('mary','June',2),('mary', 'February',5)
;with cte as
(
Select employee,[month],TotalAmount = sum(amount)
from #Employee
group by employee,[month]
)
select x.[Month],x.employee,amount = coalesce(c.TotalAmount,0)
from (
select distinct c.[Month],e.employee
from #CalenderMonths c cross join cte e)x
left join cte c on x.[Month] = c.[Month] and x.employee = c.employee
order by 2
SELECT month,employee,SUM(amount) amount
FROM(
SELECT m.month, e.employee, ISNULL(s.amount, 0) AS amount
FROM dbo.months AS m
CROSS JOIN (SELECT DISTINCT employee FROM dbo.sales) AS e
LEFT JOIN dbo.sales AS s
ON s.employee = e.employee
AND m.month = s.month
)X
GROUP BY month, employee

Top Group BY Problem DB2 [duplicate]

I've been trying for hours but can't get the query to do what I want using DB2.
From table Company and Users I have the following tickets quantity info per company/user
user company quantity
------------ ------------ ------------
mark nissan 300
tom toyota 50
steve krysler 80
mark ford 20
tom toyota 120
jose toyota 230
tom nissan 145
steve toyota 10
jose krysler 35
steve ford 100
This is generated by the query:
SELECT T.USER, COUNT(T.USER) AS QUANTITY, T.COMPANY FROM TICKET T
INNER JOIN COMPANY P ON P.COMPANY = T.COMPANY
GROUP BY (T.USER, T.COMPANY) -- ORDER BY QUANTITY DESC
What I want to see is the top user for each company, so given the data above, the query should show me:
user company quantity (Top user per company)
------------ ------------ --------------------------------
mark nissan 300
jose toyota 230
steve ford 100
steve krysler 80
How can I write the SQL to return this result?
Final answer (noted in a comment):
SELECT user, quantity, company
FROM (SELECT user, quantity, company,
RANK () OVER (PARTITION BY company ORDER BY quantity DESC) AS r
FROM (SELECT T.USER, COUNT(T.USER) AS QUANTITY, T.COMPANY
FROM TICKET T JOIN COMPANY P ON P.COMPANY = T.COMPANY
GROUP BY (T.USER, T.COMPANY) ) s ) t
WHERE r = 1;
Build it up step by step.
Find the maximum quantity for each company, assuming the first data table shown in the question is called 'Tickets':
SELECT Company, MAX(Quantity) AS MaxQuantity
FROM Tickets
GROUP BY Company;
Now, find the data for the user(s) with that maximum quantity for that company:
SELECT T.User, T.Company, M.MaxQuantity
FROM Tickets AS T
JOIN (SELECT Company, MAX(Quantity) AS MaxQuantity
FROM Tickets
GROUP BY Company) AS M
ON T.Company = M.Company AND T.Quantity = M.MaxQuantity;
If the top quantity for a particular company was, say, 200 and two users both scored 200 for that company, then this query lists both users.
Now, if you mean that the query you show in the question generates the first result table, then what I called tickets just above needs to be the derived table:
SELECT T.User, COUNT(T.User) AS Quantity, T.Ccompany
FROM Ticket AS T
INNER JOIN Company AS P ON P.Company = T.Company
GROUP BY (T.User, T.Company)
ORDER BY QUANTITY DESC
In which case, we can use a WITH clause (syntax unchecked, but I think it is correct per SQL standard):
WITH Tickets AS
(SELECT T.User, COUNT(T.User) AS Quantity, T.Ccompany
FROM Ticket AS T
JOIN Company AS P ON P.Company = T.Company
GROUP BY (T.User, T.Company)
)
SELECT T.User, T.Company, M.MaxQuantity
FROM Tickets AS T
JOIN (SELECT Company, MAX(Quantity) AS MaxQuantity
FROM Tickets
GROUP BY Company) AS M
ON T.Company = M.Company AND T.Quantity = M.MaxQuantity;
Clearly, you can also write the WITH sub-query out twice if you prefer.
This should work. Create a derived view to calculate the Quantity per user and per company. Then get the max of then Quantity and then join the max back to the the calculation of the quantity.
SELECT p.company,
t.user,
t.quantity
FROM (SELECT MAX(t.quantity) max_quantity,
t.company
FROM (SELECT
COUNT(t.user) quantity,
t.company
FROM ticket t
GROUP BY t.company) t) maxq
INNER JOIN (SELECT t.user,
t.company,
COUNT(t.user) quantity
FROM ticket t
GROUP BY t.company,
t.user) t
ON maxq.max_quantity = t.quantity
AND maxq.company = t.company
INNER JOIN company p
ON p.company = t.company
ORDER BY t.quantity DESC
A working sample that shows the top users by tag for the StackOverflow data can be found here.