How to group quantities in a period of time - sql

Im trying to group quantities regarding a time or period, i have the next table
SALES
SALES_DATE
SALES_ITEM
SALES_QUANTITY
The query that im doing it's
SELECT DATE,ITEM,SUM(QUANTITY)
FROM SALES
WHERE DATE BETWEEN "DATE1" AND "DATE2";
The problem is that i dont need the DATE to appear, if i look for the sales of october it should appear the sum of october without showing the date... Thank you very much for your help
Example:
What i get...
DATE ITEM SALES
2012-06-12 14152 7
2012-06-14 14152 15
2012-06-16 14157 25
What i need: query between 06-12 and 06-16
ITEM SALES
14152 22
14157 25
Thanks you very much

If you want the sum by month, you can include that in the group by expression. Here is one way:
SELECT extract(year from DATE) as yr, extract(month from date) as mon, ITEM, SUM(QUANTITY)
FROM SALES
WHERE DATE BETWEEN "DATE1" AND "DATE2"
group by extract(year from DATE), extract(month from date)
order by 1, 2
Although extract is standard SQL, not all databases support it. For instance, you might use to_char(date, 'YYYY-MM') in Oracle or datepart(month, date) in SQL Server.

Related

Remove Duplicates and show Total sales by year and month

i am trying to work with this query to produce a list of all 11 years and 12 months within the years with the sales data for each month. Any suggestions? this is my query so far.
SELECT
distinct(extract(year from date)) as year
, sum(sale_dollars) as year_sales
from `project-1-349215.Dataset.sales`
group by date
it just creates a long list of over 2000 results when i am expecting 132 max one for each month in the years.
You should change your group by statement if you have more results than you expected.
You can try:
group by YEAR(date), MONTH(date)
or
group by EXTRACT(YEAR_MONTH FROM date)
A Grouping function is for takes a subsection of the date in your case year and moth and collect all rows that fit, and sum it up,
So a sĀ“GROUp BY date makes no sense, what so ever as you don't want the sum of every day
So make this
SELECT
extract(year from date) as year
,extract(MONTH from date) as month
, sum(sale_dollars) as year_sales
from `project-1-349215.Dataset.sales`
group by 1,2
Or you can combine both year and month
SELECT
extract(YEAR_MONTH from date) as year
, sum(sale_dollars) as year_sales
from `project-1-349215.Dataset.sales`
group by 1

Write a query to display the total month wise sales amount received in the past 1 year

Table StructureWrite a query to display the total month wise sales amount received in the past 1 year . Display details like sales month, total sales amount. Give an alias_name as MONTH for retrieved sales month, TURN_OVER for sales amount. Sort the result by amount in descending order.
(Hint: Use table Sales_info. Use to_char for retrieving the month. Net amount for sales amount calculation. Use sysdate for calculation of past 1 year sales. DATA IS CASE-SENSITIVE.)
The code I have written is fetching me all years sales data.
select to_char(Sales_Date,'Month')"MONTH"
Net_Amount as Turn_Over
from Sales_Info
where Sales_Date= add_months(Sysdate,-12)
select to_char(Sales_Date,'MON')"MONTH",
Net_Amount as TURN_OVER
from Sales_Info
where Sales_Date > add_months(Sysdate,-12)
order by Net_Amount desc;
I'm not going to do your homework for you, but here is a list of things currently missing from your query:
a comma in the SELECT list
you need greater than, not equals because you want all dates "more than the moment it was a year ago"
you need to break your data into groups where each group has the same month, and you need to sum up all the data in that month, so your query needs to have the words GROUP BY and SUM in it..
The code I have written is fetching me all years sales data
No, the query as it stands will be giving you only the sales that happened at exactly the current date-time, one year ago, which is probably 0 records
You are pretty close. What you are missing is the GROUP BY and summary functions:
select to_char(Sales_Date, 'Month') as "MONTH"
SUM(Net_Amount) as Turn_Over
from Sales_Info
where Sales_Date= add_months(Sysdate, -12)
group by to_char(Sales_Date, 'Month');
Note that there are still some significant issues with the query. For instance, I really am not a fan of using month names for what you are doing. It leaves out the year. In fact, the above query is going to combine data from the current month and the same month last year.
I would instead go for complete months. And use trunc() instead:
select trunc(Sales_Date, 'MON') as "MONTH"
SUM(Net_Amount) as Turn_Over
from Sales_Info
where Sales_Date = add_months(trunc(Sysdate, 'MON'), -12) and
Sales_Date < trunc(sysdate, 'MON')
group by to_char(Sales_Date, 'Month')
order by "MONTH".
In a real-world environment, this would typically provided cleaner, more useful results. In addition, because the first column is actually the date, it is easy to sort by.
The ans will be :
Select to_char(Sales_Date , 'MON' ) as "MONTH" , sum(Net_Amount) as TURN_OVER
from Sales_Info
where Sales_Date > add_months(Sysdate , -12)
group by to_char(Sales_Date , 'MON')
order by TURN_OVER desc;

How to aggregate YTD measure dynamically

I have a table which has 2 fields timestamp and count. Table has data since 2016 November.
I have to set up a query which will daily aggregate the YTD sum(count) for all the years. I am not using calendar year definition but rather November-October (Next year). This shouldn't ideally change the logic
2017: 11/01/2016-10/31/2017;
2018: 11/01/2017-10/31/2018;
2019: 11/01/2018-10/31/2019;
2020: 11/01/2019-10/31/2020
I want a query that will calculate on any given day aggregate YTD with November 1st as the start date. I tried this query
select ytd_bucket
,sum(count_field) sum
from
(
select
timestamp_field,
count_field,
CASE
WHEN DATE(timestamp_field,"America/Los_Angeles") >= '2019-11-01' THEN '2020'
WHEN DATE(timestamp_field,"America/Los_Angeles") BETWEEN '2018-11-01' AND CAST(CONCAT('2019-',FORMAT_DATE('%m-%d', DATE(CURRENT_TIMESTAMP(),"America/Los_Angeles"))) AS DATE) THEN '2019'
WHEN DATE(timestamp_field,"America/Los_Angeles") BETWEEN '2017-11-01' AND CAST(CONCAT('2018-',FORMAT_DATE('%m-%d', DATE(CURRENT_TIMESTAMP(),"America/Los_Angeles"))) AS DATE) THEN '2018'
WHEN DATE(timestamp_field,"America/Los_Angeles") BETWEEN '2016-11-01' AND CAST(CONCAT('2017-',FORMAT_DATE('%m-%d', DATE(CURRENT_TIMESTAMP(),"America/Los_Angeles"))) AS DATE) THEN '2017'
ELSE NULL END as YTD_bucket
from table
)
group by 1
The above query does not aggregate the numbers are a YTD level. For the years prior to 2020 (ytd_bucket) the query is aggregating the entire years count.
Start by aggregating per day:
select date(timestamp_field, 'America/Los_Angeles') as dte,
count(*)
from table
group by dte;
Then, for the YTD, you want to add one year and get the date:
select dte,
count(*),
sum(count(*)) over (partition by extract(year from date_add(dte, interval 1 month))
order by min(timestamp_field)
) as running_cnt
from (select t.*,
date(timestamp_field, 'America/Los_Angeles') as dte
from t
) t
group by dte;

Using Date to find the inequality for sales than 500

I'm curious as to find the daily average sales for the month of December 1998 not greater than 100 as a where clause. So what I imagine is that since the table consists of the date of sales (sth like 1 december 1998, consisting of different date, months and year), amount due....First I'm going to define a particular month.
DEFINE a = TO_DATE('1-Dec-1998', 'DD-Month-YYYY')
SELECT SUBSTR(Sales_Date, 4,6), (SUM(Amount_Due)/EXTRACT(DAY FROM LAST_DAY(Sales_Date))
FROM ......
WHERE SUM(AMOUNT_DUE)/EXTRACT(DAY FROM LAST_DAY(&a)) < 100
I'm stuck as to extract the sum of amount due in the month of december 1998 for the where clause....
How can I achieve the objective?
To me, it looks like this:
select to_char(sales_date, 'mm.yyyy') month,
avg(amount_due) avg_value
from your_table
where sales_date >= trunc(date '1998-12-01', 'mm')
and sales_date < add_months(trunc(date '1998-12-01', 'mm'), 1)
group by to_char(sales_date, 'mm.yyyy')
having avg(amount_due) < 100;
WHERE clause can be simplified; it shows how to fetch certain period:
trunc to mm returns first day in that month
add_months to the above value (first day in that month) will return first day of the next month
the bottom line: give me all rows whose sales_date is >= first day of this month and < first day of the next month; basically, the whole this month
Finally, the where clause you used should actually be the having clause.
As long as the amount_due column only contains numbers, you can use the sum function.
Below SQL query should be able to satisfy your requirement.
Select SUM(Amount_Due) from table Sales where Sales_Date between '1-12-1998' and '31-12-1998'
OR
Select SUM(Amount_Due) from table Sales where Sales_Date like '%-12-1998'

Sorting months while im converting them to text

I have to do a consult which must give me the following information:
Month | Quantity
-------------------
January | XX
February | XX
... | ..
So, I thought in:
select to_char(to_timestamp(to_char(date_part('month', orderdate), '999'), 'MM'), 'Mon'), count(*) as quantity from orders group by 1 ORDER BY 1
The problem is: months were sorted by "text" I mean:
Apr
Aug
Dec
...
How to solve it?
I suggest date_trunc() instead. It truncates date / timestamp to the given unit.
For two reasons:
You want the number of orders in August of a particular year, like 2012, not the sum for August of all years in the table. date_trunc('month', orderdate) does exactly that and prevents that you mix multiple years by accident. You get multiple rows for multiple years.
You can both ORDER BY and GROUP BY this one expression, the query is a bit faster.
SELECT to_char(date_trunc('month', orderdate), 'Mon') AS "Month" -- repeat expr.
,count(*) AS "Quantity"
FROM orders
GROUP BY date_trunc('month', orderdate) -- 1 item covers it
ORDER BY date_trunc('month', orderdate);
db<>fiddle here
Old sqlfiddle
For full month names, like your first example implies:
to_char(date_col, 'Month')
For non-English, localized names:
to_char(date_col, 'TMMonth')
Details in the manual.
First of all, your to_char is a lot more complicated that it needs to be, just this:
to_char(orderdate, 'Mon')
should be sufficient.
You're grouping and ordering by the first value that you select, that's what your 1 means. So of course the results are being sorted by month name, that's what you're asking for. Instead you want to group and order by the month component of the date, not its string representation. Something like this:
select to_char(orderdate, 'Mon') as "Month",
count(*) as "Quantity"
from orders
group by extract(month from orderdate), to_char(orderdate, 'Mon')
order by extract(month from orderdate)
You need both values in the GROUP BY to make it play nice with both your SELECT and your ORDER BY at the same time.