Return first order by each month - sql

I am trying to modify my current query to return the first order for each month in each year.
Here is my full table and my current query.
select orderdate, sum(UnitPrice*Qty)
AS month_firstOrder_total
from OrderByDate
group by OrderDate

Try something like this:
WITH DataSource AS
(
select *
,ROW_NUMBER() OVER (PARTITION BY YEAR(orderdate), MONTH(orderdate) ORDER BY orderdate ASC) rn
from OrderByDate
)
SELECT *
FROM DataSource
WHERE rn = 1;
You can get the total sum per order date if you want, too:
WITH DataSource AS
(
select *
,ROW_NUMBER() OVER (PARTITION BY YEAR(orderdate), MONTH(orderdate) ORDER BY orderdate ASC) rn
,sum(UnitPrice*Qty) OVER (PARTITION BY orderdate) as sum_qty
from OrderByDate
)
SELECT *
FROM DataSource
WHERE rn = 1

Could you create a MONTH column?
Then you select Min(id) and order by MONTH.
I just guess
select *
from
(select min(id), month, sum(UnitPrice * Qty)
from your_table_name
group by month)

Related

How to get min value at max date in sql?

I have a table with snapshot data. It has productid and date and quantity columns. I need to find min value in the max date. Let's say, we have product X: X had the last snapshot at Y date but it has two snapshots at Y with 9 and 8 quantity values. I need to get
product_id | date | quantity
X Y 8
So far I came up with this.
select
productid
, max(snapshot_date) max_date
, min(quantity) min_quantity
from snapshot_table
group by 1
It works but I don't know why. Why this does not bring min value for each date?
I would use RANK here along with a scalar subquery:
WITH cte AS (
SELECT *, RANK() OVER (ORDER BY quantity) rnk
FROM snapshot_table
WHERE snapshot_date = (SELECT MAX(snapshot_date) FROM snapshot_table)
)
SELECT productid, snapshot_date, quantity
FROM cte
WHERE rnk = 1;
Note that this solution caters to the possibility that two or more records happened to be tied for having the lower quantity among those most recent records.
Edit: We could simplify by doing away with the CTE and instead using the QUALIFY clause for the restriction on the RANK:
SELECT productid, snapshot_date, quantity
FROM snapshot_table
WHERE snapshot_date = (SELECT MAX(snapshot_date) FROM snapshot_table)
QUALIFY RANK() OVER (ORDER BY quantity) = 1;
Consider also below approach
select distinct product_id,
max(snapshot_date) over product as max_date,
first_value(quantity) over(product order by snapshot_date desc, quantity) as min_quantity
from your_table
window product as (partition by product_id)
use row_number()
with cte as (select *,
row_number() over(partition by product_id order by date desc) rn
from table_name) select * from cte where rn=1

Top N items in every month - BIGQUERY

I have a big query program below;
WITH cte AS(
SELECT *
FROM (
SELECT project_name,
SUM(reward_value) AS total_reward_value,
DATE_TRUNC(date_signing, MONTH) as month,
date_signing,
Row_number() over (partition by DATE_TRUNC(date_signing, MONTH)
order by SUM(reward_value) desc) AS rank
FROM `deals`
WHERE CAST(date_signing as DATE) > '2019-12-31'
AND CAST(date_signing as DATE) < '2020-02-01'
AND target_category = 'achieved'
AND project_name IS NOT NULL
GROUP BY project_name, month, date_signing
)
)
SELECT * FROM cte WHERE rank <= 5
that returns the following result:
While I expect to have each unique project to be SUM within each month and then I filter only the top 5.
Something like this:
I got the following error if the date_signing grouping is removed
PARTITION BY expression references column date_signing which is neither grouped nor aggregated at [16:48]
Any hints what should be corrected will be appreciated!
One more subquery maybe then?
WITH cte AS(
SELECT project_name,
SUM(reward_value) as reward_sum,
DATE_TRUNC(date_signing, MONTH) as month
FROM `deals`
WHERE CAST(date_signing as DATE) > '2019-12-31'
AND CAST(date_signing as DATE) < '2020-02-01'
AND target_category = 'achieved'
AND project_name IS NOT NULL
GROUP BY project_name, month
),
ranks AS (
SELECT
project_name,
reward_sum,
month,
ROW_NUMBER() over (PARTITION BY month ORDER BY reward_sum DESC) AS rank
)
SELECT *
FROM ranks
WHERE rank <= 5
yeah you can't do that , yo can show the last signing date instead:
WITH cte AS(
SELECT project_name,
SUM(reward_value),
DATE_TRUNC(date_signing, MONTH) as month,
MAX(date_signing) as last_signing_date,
Row_number() over (partition by DATE_TRUNC(date_signing, MONTH)
order by SUM(reward_value) desc) AS rank
FROM `deals`
WHERE CAST(date_signing as DATE) > '2019-12-31'
AND CAST(date_signing as DATE) < '2020-02-01'
AND target_category = 'achieved'
AND project_name IS NOT NULL
GROUP BY project_name, month
)
SELECT * FROM cte WHERE rank <= 5

How to select last record from table consider to Year and WorkingPeriod(Month)

I have a table like this:
I want last [Status] for each [Guid], consider to latest [Year] and [WorkingPeriodTitle].
By the way I know that [WorkingPeriodTitle] should be replace by [WorkingPeriodId].
With ROW_NUMBER() window function:
select
t.[PaymentAllocationGuid], t.[Status]
from (
select *,
row_number() over (partition by [PaymentAllocationGuid] order by [Year] desc, [WorkingPeriodTitle] desc) rn
from tablename
) t
where t.rn = 1
SELECT *,
LAST_VALUE(Status) OVER (PARTITION BY PaymentAllocationGuid ORDER BY Year,
WorkingPeriodTitle RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
AS LastStatus
FROM tablexyz

Retrieve recent 5 days forecast for each cities with latest issue date

I need to retrieve the recent 5 days forecast info for each cities.
My table looks like below
The real problem is with the issue date.
the city may contain several forecast info for the same date with distinct issue date.
I need to retrieve recent 5 records for each cities with latest issue date and group by forecast date
I have tried something like below but not giving the expected result
SELECT * FROM(
SELECT
ROW_NUMBER () OVER (PARTITION BY CITY_ID ORDER BY FORECAST_DATE DESC, ISSUE_DATE DESC) AS rn,
CITY_ID, FORECAST_DATE, ISSUE_DATE
FROM
FORECAST
GROUP BY FORECAST_DATE
) WHERE rn <= 5
Any suggestion or advice will be helpful
This will get the latest issued forecast per day over the most recent 5 days for each city:
SELECT *
FROM (
SELECT f.*,
DENSE_RANK() OVER ( PARTITION BY city_id ORDER BY forecast_date DESC )
AS forecast_rank,
ROW_NUMBER() OVER ( PARTITION BY city_id, forecast_date ORDER BY issue_date DESC )
AS issue_rn
FROM Forecast f
)
WHERE forecast_rank <= 5
AND issue_rn = 1;
Partition by works like group by but for the function only.
Try
with CTE as
(
select t1.*,
row_number() over (partition by city_id, forecast_date order by issue_date desc) as r_ord
from Forecast
)
select CTE.*
from CTE
where r_ord <= 5
Try this
SELECT * FROM(
SELECT
ROW_NUMBER () OVER (PARTITION BY CITY_ID, FORECAST_DATE order by ISSUE_DATE DESC) AS rn,
CITY_ID, FORECAST_DATE, ISSUE_DATE
FROM
FORECAST
) WHERE rn <= 5

SQL Select MAX and 2nd MAX

I am running a query against MS SQL Server 2008 and am selecting an accountnumber and the max of the column mydate grouped by accountnumber:
select AccountNumber,
max(mydate),
from #SampleData
group by AccountNumber
I want to add a column to the result that contains the second highest mydate that is associated with the AccountNumber group. I know it would have to be something like:
select max(mydate)
from #SampleData
where mydate < (select max(mydate) from #SampleData)
But how do I get both the max and 2nd max in one select query?
You didn't specify your DBMS so this is ANSI SQL:
select accountnumber,
rn,
mydate
from (
select accountnumber,
mydate,
row_number() over (partition by accountnumber order by mydate desc) as rn
from #SampleData
) t
where rn <= 2;
Try this
Select AccountNumber,
MAX(Case when Rnum = 1 Then mydate END) mydate_1,
MAX(Case when Rnum = 2 Then mydate END) mydate_2
From
(
select
AccountNumber, mydate,
ROW_NUMBER() OVER (PARTITION By AccountNumber ORDER BY mydate DESC) as Rnum
from #SampleData
) V
Group By AccountNumber
Something like this should select the second highest:
select AccountNumber,
max(mydate),
(select max(SD2.mydate) from #SampleData SD2 where SD2.AccountNumber=#SampleData.AccountNumber AND SD2.mydate<max(#SampleData.mydate))
from #SampleData
group by AccountNumber
You could also use a TOP N clause combined with an order by:
select
TOP 2
accountnumber,
mydate,
row_number() over (partition by accountnumber order by mydate desc) as rn
from #SampleData
ORDER BY
row_number() over (partition by accountnumber order by mydate desc)