In my structure I have the following, I would like to keep (yellow) the most recent dates and delete the remaining? I don't necessary know the most recent date (ie 17/4/2021 and 10/2/2021 in my example) for each stock_id but I know I want to keep only the two most recent items.
Is that possible?
Thank you
Note: this assumes that dates do not repeat within each stock_id group in your table, so top two dates are always unique.
You can assign rank to each row within stock_id after ordering by date and delete rows where rank is greater than 2.
DELETE FROM mytable
WHERE (stock_id, date) NOT IN (
SELECT
stock_id,
date
FROM (
SELECT
stock_id,
date,
row_number() over (partition by stock_id order by date desc) as rank
FROM mytable
) ranks
WHERE rank <= 2
)
Good morning,
I have a problem I've been trying to solve for but am getting now where.
I need to find the max date of the previous month. Normally I would just use the following to find the last day of the previous month: last_day(add_months(current_date, -1)
However, this particular data set doesn't always have the last day with data. E.g. Last day in the data for May was May 30th. Obviously if i try using the syntax above it would return no data because it would be looking for 5/31.
So is there a way to find the "max" day available in the data of the previous month? Or the month prior etc.?
For example like this (two scans of table: one in subquery to find max date and one in main query):
select *
from mytable
where as_of_date in (select max(as_of_date) from mytable where as_of_date between first_day(add_months(current_date, -1)) and last_day(add_months(current_date, -1))
Or (single scan + analytic function) like this
select col1 ... colN
from
(
select t.*, rank() over (partition by month (t.as_of_date) order by t.as_of_date desc) rnk
from mytable t
where --If you have partition on date, this WHERE may improve performance
t.as_of_date between first_day(add_months(current_date, -1)) and last_day(add_months(current_date, -1))
)s
where rnk=1
I am trying to figure out the aggregate functions in SQL SSRS to give me to sum of total sales for the given information by YEAR. I need to combine the year, the months within that year and provide the total sum of sales for that year. For example: for 2018 I need to combine month's 2-12 and provide the total sum, for 2019 combine 1-12 and provide total sum and so on.
enter image description here
I'm not sure where to begin on this one as I am new to SQL SSRS. Any help would be appreciated!
UPDATE:
Ideally I want this to be the end result:
id Year Price
102140 2019 ($XXXXX.XX)
102140 2018 ($XXXXX.XX)
102140 2017 ($XXXXX.XX)
And so on.
your query:
Select customer_id
, year_ordered
--, month_ordered
--, extended_price
--, SUM(extended_price) OVER (PARTITION BY year_ordered) AS year_total
, SUM(extended_price) AS year_total
From customer_order_history
Where customer_id = '101646'
Group By
customer_id
, year_ordered
, extended_price
--, month_ordered
Provides this:
enter image description here
multiple "years_ordered" because it is still using each month and that months SUM of price.
There are two approaches.
Do this in your dataset query:
SELECT Customer_id, year_ordered, SUM(extended_price) AS Price
FROM myTable
GROUP BY Customer_id, year_ordered
This option is best when you will never need the month values themselves in the report (i.e. you don't intend to have a drill down to the month data)
Do this in SSRS
By default you will get a RowGroup called "Details" (look under the main design area and you will row groups and column groups).
You can right-click this and add grouping for both customer_id and year_ordered. You can then change the extended_price textbox's value property to =SUM(Fields!extended_price.Value)
You could use a window function in your SQL:
select [year], [month], [price], SUM(PRICE) OVER (PARTITION BY year) as yearTotal
from myTable
I've just begun using Postgresql recently. I have a table named 'sales'.
create table sales
(
cust varchar(20),
prod varchar(20),
day integer,
month integer,
year integer,
state char(2),
quant integer
)
insert into sales values ('Bloom', 'Pepsi', 2, 12, 2001, 'NY', 4232);
insert into sales values ('Knuth', 'Bread', 23, 5, 2005, 'PA', 4167);
insert into sales values ('Emily', 'Pepsi', 22, 1, 2006, 'CT', 4404);
insert into sales values ('Emily', 'Fruits', 11, 1, 2000, 'NJ', 4369);
insert into sales values ('Helen', 'Milk', 7, 11, 2006, 'CT', 210);
...
There are 500 rows, 10 distinct products and 5 distinct customers in total.
It looks like this:
Now I need to , find the most “popular” and least “popular” products (those products with most and least total sales quantities) and the corresponding total sales quantities (i.e., SUMs) for each of the 12 months (regardless of the year).
The result should be like this:
Now I can only write query like this:
select month,
prod,
sum(quant)
from sales
group by month,prod
order by month,prod;
And it gives me the result like this:
Now I need to pick up the maximum value for each month. For example, the biggest value in the first 10 sums of month 1, and so on...
I also need to get the minimum value of the sums (regardless of the year). And combine them horizontally... I have no idea about this...
Note: for a TLDR, skip to the end.
Your problem is a very interesting textbook case as it involves multiple facets of Postgres.
I often find it very helpful to decompose the problem into multiple subproblems before joining them together for the final result set.
In your case, I see two subproblems: finding the most popular product for each month, and finding the least popular product for each month.
Let's start with the most popular products:
WITH months AS (
SELECT generate_series AS month
FROM generate_series(1, 12)
)
SELECT DISTINCT ON (month)
month,
prod,
SUM(quant)
FROM months
LEFT JOIN sales USING (month)
GROUP BY month, prod
ORDER BY month, sum DESC;
Explanations:
WITH is a common table
expression,
which acts as a temporary table (for the duration of the query) and
helps clarify the query. If you find it confusing, you could also opt
for a subquery.
generate_series(1, 12) is a Postgres function which generate a series of integers, in this case from 1 to 12.
the LEFT JOIN allows us to associate each sale to the corresponding month. If no sale can be found for a given month, a row is returned with the month and the joined columns with NULL values. More information on joins can be found here. In your case, using LEFT JOIN is important, as using INNER JOIN would exclude products that have never been sold (which in that case should be the least popular product).
GROUP BY is used to sum over the quantities.
at this stage, you should -potentially- have multiple products for any given month. We only want to keep those with the most quantities for each month. DISTINCT ON is especially useful for that purpose. Given a column, it allows us to keep the first iteration of each value. It is therefore important to ORDER the sales by sum first, as only the first one will be selected. We want the bigger numbers first, so DESC (for descending order) should be used.
We can now repeat the process for the least popular products:
WITH months AS (
SELECT generate_series AS month
FROM generate_series(1, 12)
)
SELECT DISTINCT ON (month)
month,
prod,
SUM(quant)
FROM months
LEFT JOIN sales USING (month)
GROUP BY month, prod
ORDER BY month, sum;
Conclusion (and TLDR):
Now we need to merge the two queries into one final query.
WITH months AS (
SELECT generate_series AS month
FROM generate_series(1, 12)
), agg_sales AS (
SELECT
month,
prod,
SUM(quant)
FROM months
LEFT JOIN sales USING (month)
GROUP BY month, prod
), most_popular AS (
SELECT DISTINCT ON (month)
month,
prod,
sum
FROM agg_sales
ORDER BY month, sum DESC
), least_popular AS (
SELECT DISTINCT ON (month)
month,
prod,
sum
FROM agg_sales
ORDER BY month, sum
)
SELECT
most_popular.month,
most_popular.prod AS most_popular_prod,
most_popular.sum AS most_pop_total_q,
least_popular.prod AS least_popular_prod,
least_popular.sum AS least_pop_total_q
FROM most_popular
JOIN least_popular USING (month);
Note that I used an intermediate agg_sales CTE to try and make the query a bit clearer and avoid repeating the same operation twice, although it shouldn't be a problem for Postgres' optimizer.
I hope you find my answer satisfactory. Do not hesitate to comment otherwise!
EDIT: although this solution should work as is, I would suggest storing your dates as a single column of type TIMESTAMPTZ. It is often much easier to manipulate dates using that type and it is always good practice in case you need to analyze and audit your database further down the line.
You can get the month of any date by simply using EXTRACT(MONTH FROM date).
I am currently using SQL Server 2008R2.
I would like to create a script that shows, per month, a grand total plus a % value of the items that come through in the name field.
This is the script I am currently using:
SELECT
a.name,
DATENAME(M, a.Date) as Month,
DATENAME(YEAR,a.Date) as Year,
DATEPART(YYYY, a.Date) as YearNum,
DATEPART (M, a.Date) as MonthNum,
COUNT(*) as [Total]
FROM Database1.Table1 as a
WHERE a.name = 'active'
GROUP BY a.name, DATENAME(month, a.Date),
DATENAME(year, a.Date), DATEPART(YYYY, a.date), DATEPART (M, a.date)
ORDER BY Month desc;
Is it possible, in the select statement above, to create a monthly total for all products (a.name)? At the moment, the above script gives a total per name, e.g.
Television 25
Radio 25
In addition, it would be good to also see a % total as well, per name item, so for example Television 50%
Any help much appreciated – thanks!
Used CTE to solve the problem.