Creating Average based on Subtracted Data in Postgres - sql

I want to count the number of books delivered per country, per month and also generate the average time it took to deliver the book.
I have the following columns book_title, Country_Delivered, OrderDate, DeliveryDate
The results should look like this;
|Country|Month|Number_Books|Average_Delivery|
I am using Postgres

select to_char(OrderDate, 'YYYY-MM') year_month
, Country
, count(*) Number_Books
, avg(DeliveryDate - OrderDate) Average_Delivery_days
from tablename
group by to_char(OrderDate, 'YYYY-MM') ,Country

Related

Find number of customers and orders and group by month (Bigquery)

I need to get monthly sales numbers in each Country & region.
Also - a number of orders, customers and sales persons in each month with a total amount.
I got stuck as I cannot understand how to make all counts/sum and also group by month as I only have daily data.
I have tried something like this:
SELECT
orderdate,
TerritoryID,
(
SELECT
COUNT(SalesOrderID)
FROM
adwentureworks_db.salesorderheader),
COUNT(DISTINCT CustomerID) SalesPersonID,
SUM(totaldue)
FROM
adwentureworks_db.salesorderheader
GROUP BY
OrderDate,
TerritoryID,
TotalDue`
It should look like this:
Data:
The 1st day of a month can be obtained by date_trunc(orderdate,month)
For the inner SELECT, I do not know what you want to archive. The total number can be obtained by a window function count(...) over().
Select
date_trunc(orderdate,month),
TerritoryID,
COUNT(DISTINCT CustomerID) as SalesPersonID,
SUM(totaldue) as totaldue,
COUNT(SalesOrderID) over () as totalsalesorder_of_whole_table
FROM adwentureworks_db.salesorderheader
GROUP BY 1,2

Calculate month on month growth rate of orders for the last 3 months for each country

I am trying to find the month on month growth rate of orders for the past 3 months for each country.
So far I have tried:
select date_part('month', order_date) as mnth,
country_id,
100 * (count() - lag(count(), 1) over (order by order_date)) / lag(count(), 1) over (order by order_date) as growth
from orders
and order_date >= DATEADD(DAY, -90, GETDATE())
group by country_id;
When we GROUP BY country_id, we produce a result of rows, one per country.
The aggregate COUNT will then operate on one group for each country and the subsequent window function (LAG) won't see more than one row for each country.
There's no way, in this context, LAG can be used to obtain data for a prior month for the same country.
GROUP BY country_id, date_part('month', order_date) is one approach that could be used. Be sure to LAG OVER PARTITIONs for each country, ordered by date.
Here's a small change in your SQL that might help (not tested and just a starting point).
Note: I used SQL Server to test below. Convert datepart to date_part as needed.
Fiddle for SQL Server
WITH cte AS (
SELECT *, datepart(month, order_date) AS mnth
FROM orders
WHERE order_date >= DATEADD(DAY, -90, GETDATE())
)
SELECT mnth
, country_id
, 100 * (COUNT(*) - LAG(COUNT(*)) OVER (PARTITION BY country_id ORDER BY mnth)) / LAG(COUNT(*)) OVER (PARTITION BY country_id ORDER BY mnth) AS growth
FROM cte
GROUP BY country_id, mnth
;

How to get transaction count per year in SQL

I want to get yearly transaction every category
SELECT DATEPART(YEAR, trans_date) AS YEAR, SUM(CAST(doc_no as int))
FROM transac_tbl1 WHERE agent_id IN ('transaction1', 'transaction2')
GROUP BY trans_date
You obviously have an issue with the GROUP BY. I would also suggest the YEAR() function:
SELECT YEAR(trans_date) AS YEAR, SUM(doc_no)
FROM transac_tbl1
WHERE agent_id in ('transaction1', 'transaction2')
GROUP BY YEAR(trans_date);
I'm not sure why you are casting doc_no to an int. I wonder if you really just want the count:
SELECT YEAR(trans_date) AS YEAR, COUNT(*)
FROM transac_tbl1
WHERE agent_id in ('transaction1', 'transaction2')
GROUP BY YEAR(trans_date);

Accumulating values until up to date

I'm working on an order system where orders come in. For the analytics department I want to build a view that accumulates all sales for a given day.
That is not an issue, I got the working query for that. More complicated is a second number where I want to show the accumulated sales to that day.
Meaning if I have $100 of sales on Feb 1 the column should show $100. If I have $200 of sales on Feb 2 that column should show $300 and so on.
This is what I came up with so far:
select
date_trunc('day', o.created_at) :: date,
sum(o.value) sales_for_day,
count(o.accepted_at) as num_of_orders_for_day,
-- sales_for_month_to_date
-- num_of_orders_for_month_to_date
from
orders o
where
status = 'accepted'
group by
date_trunc('day', o.accepted_at);
Just use window functions:
select date_trunc('day', o.created_at) :: date,
sum(o.value) as sales_for_day,
count(o.accepted_at) as num_of_orders_for_day,
sum(sum(o.value)) over (partition by date_trunc('month', o.accepted_at order by min(o.created_at)) as sales_for_month_to_date
sum(count(*)) over (partition by date_trunc('month', o.accepted_at order by min(o.created_at)) as num_of_orders_for_month_to_date
from orders o
where status = 'accepted'
group by date_trunc('day', o.accepted_at);
Based on the comments in your code, I surmise that you want month-to-date numbers, so this also partitions by month.

SQL: aggregation (group by like) in a column

I have a select that group by customers spending of the past two months by customer id and date. What I need to do is to associate for each row the total amount spent by that customer in the whole first week of the two month time period (of course it would be a repetition for each row of one customer, but for some reason that's ok ). do you know how to do that without using a sub query as a column?
I was thinking using some combination of OVER PARTITION, but could not figure out how...
Thanks a lot in advance.
Raffaele
Query:
select customer_id, date, sum(sales)
from transaction_table
group by customer_id, date
If it's a specific first week (e.g. you always want the first week of the year, and your data set normally includes January and February spending), you could use sum(case...):
select distinct customer_id, date, sum(sales) over (partition by customer_ID, date)
, sum(case when date between '1/1/15' and '1/7/15' then Sales end)
over (partition by customer_id) as FirstWeekSales
from transaction_table
In response to the comments below; I'm not sure if this is what you're looking for, since it involves a subquery, but here's my best shot:
select distinct a.customer_id, date
, sum(sales) over (partition by a.customer_ID, date)
, sum(case when date between mindate and dateadd(DD, 7, mindate)
then Sales end)
over (partition by a.customer_id) as FirstWeekSales
from transaction_table a
left join
(select customer_ID, min(date) as mindate
from transaction_table group by customer_ID) b
on a.customer_ID = b.customer_ID