SQL query assign days to periods based on end date - sql

I have a table that has a list of dates from now till 2015.
eg.
Date
11/1/2013
12/1/2013
13/1/2013
...
25/1/2013
I have a separate table this holds report dates.
cutoff_ date purpose
11/1/2013 Mid Month Report
25/1/2013 Month End Report
So I need to assign a the dates between 11/1/2013 and 25/1/2013 all to 25/1/2013 whats the best way to go about this?
Can I do it in a simple SQL query?
The DB is currently in Access if that makes a difference

Use DMin to retrieve the minimum cutoff_date which is greater than or equal to [Date].
SELECT
[Date],
DMin("cutoff_date", "report_dates",
"[cutoff_date] >= " & Format([Date], "\#yyyy-m-d\#")) AS report_date
FROM first_table;

There can be advantages to using subqueries, for example, you can use a parameter, which can be assigned in code, got from a form, or simply typed in. This example selects only those records that have a date that matches the cutoff_date purpose entered in the prompt [please enter purpose].
SELECT DISTINCT dates.day,
(SELECT TOP 1 cutoff_date
FROM report_dates
WHERE cutoff_date >= dates.day
AND purpose = [please enter purpose]
ORDER BY cutoff_date) AS CutOff
FROM dates
WHERE (SELECT TOP 1 cutoff_date
FROM report_dates
WHERE cutoff_date >= dates.day
AND purpose = [please enter purpose]
ORDER BY cutoff_date) IS NOT NULL;

Related

Average price based on dates

I am trying to calculate a weekly average, and add it as a new column along side what I already have. I have added week starting dates and week ending dates as I thought that would be useful (and how I found do it in a more familiar MS Excel environment).
SELECT
settlementdate as Trading_Interval,
rrp as Trading_Interval_QLD_RRP,
NEXT_DAY(TRUNC(settlementdate-7),'MONDAY')AS Week_Starting,
NEXT_DAY(TRUNC(settlementdate),'SUNDAY')AS Week_Ending
FROM fullauth.tradingprice
WHERE settlementdate > to_date('31/12/2019','dd/mm/yyyy')
AND settlementdate <= to_date('01/01/2020','dd/mm/yyyy')
AND regionid = 'QLD1'
ORDER BY settlementdate DESC;
This code returns a table with 4 columns. I want to find the average price of the Trading_Interval_QLD_RRP when the Trading_Interval falls between the Week_Starting and Week_Ending dates and insert/create this weekly price as a new column
Thanks!
You can use AVG as an analytical function as following:
SELECT
settlementdate as Trading_Interval,
rrp as Trading_Interval_QLD_RRP,
NEXT_DAY(TRUNC(settlementdate-7),'MONDAY')AS Week_Starting,
NEXT_DAY(TRUNC(settlementdate),'SUNDAY')AS Week_Ending,
-- required changes as following
AVG(Trading_Interval_QLD_RRP) OVER (PARTITION BY TRUNC(settlementdate,'IW')) AS AVG_RRP
FROM fullauth.tradingprice
WHERE settlementdate > to_date('31/12/2019','dd/mm/yyyy')
AND settlementdate <= to_date('01/01/2020','dd/mm/yyyy')
AND regionid = 'QLD1'
ORDER BY settlementdate DESC;
Also, Note that TRUNC(settlementdate,'IW') and NEXT_DAY(TRUNC(settlementdate-7),'MONDAY') are same.
Cheers!!

SQL minimum date value after today's date Now()

I am writing a query and am having trouble filtering data as I would like. In the table, there is a date field and an ItemCode field. I would like to return one record per ItemCode with the earliest date that is after today.
If today is 6/6/2017 and my data looks like:
ItemCode Date
1 6/1/2017
1 6/7/2017
1 6/10/2017
2 6/2/2017
2 6/8/2017
2 6/15/2017
I would want the result to be
ItemCode Date
1 6/7/2017
2 6/8/2017
My query so far is:
SELECT PO_PurchaseOrderDetail.ItemCode, Min(PO_PurchaseOrderDetail.RequiredDate) AS NextPO
FROM PO_PurchaseOrderDetail
GROUP BY PO_PurchaseOrderDetail.ItemCode
HAVING (((Min(PO_PurchaseOrderDetail.RequiredDate))>=Now()));
The problem is that the Min function fires first and grabs the earliest dates per ItemCode, which are before today. Then the >=Now() is evaluated and because the min dates are before today, the query returns nothing.
I've tried putting the >=Now() inside the min function in the HAVING part of the query but it does not change the result.
My structure is wrong and I would appreciate any advice. Thanks!
I would approach like this for standard SQL, Access approach may vary
select PO_PurchaseOrderDetail.ItemCode,
min(PO_PurchaseOrderDetail.RequiredDate) as NextPO
from PO_PurchaseOrderDetail
where PO_PurchaseOrderDetail.RequiredDate >= Now()
group by PO_PurchaseOrderDetail.ItemCode;
Put the date condition in the where clause (not the having clause):
select ItemCode, min(Date) as NextPO
from PO_PurchaseOrderDetail
where Date > '6/6/2017'
group by ItemCode

SSRS Report Multi Parameters (start date,end date, MeterId, Displayby)

In my SSRS report there are 4 parameters StartDate, EndDate, MeterId, & DisplayBy
Start Date: datetime datatype
EndDate : datetime datatype
MeterId : is a drop down list and this will populate based on SQL query
DisplayBy: is a drop down list and this has the following values (Hour,day,Month & year)
The Database that stores hourly values for Meters, the following are the DB table columns: (MeterId,ReadingDate,Hours,Quantity,Price)
When I select the startdate, end date and the meter Id and display i want to show report based on the startdate & enddate and then by display values.
If the display is hour, the we got display all the 24 hour values for the MeterId,Quantity, Price for the date range.
If the display is day, we got display total quantity and total price for the MeterId for that date range.
If the display is Month, we got display total quantity and total price for the MeterId for that date range.
If the display is Year, we got display total quantity and total price for the MeterId for that date range. Say for example If i select start date as 1-1-2016 and end date as 12-31-2016. My result should show 12 rows for each month with their total Quantity, Total price for that particular MeterID.
my DB table stores all the hourly values i know how to show the values on screen if the user selects the display dropdown as hour. But, dont know how to show the result for day/month/year or how to group it. Do I need to use "case" statement and if so what should i need to give on display parameters.
Please suggest your idea...
Row Grouping:
SELECT I.CustomerName, I.ReadingDate, I.IntegratedHour, I.IntegratedUsage, I.IntegratedGeneration, DATEPART(dd, I.ReadingDate) AS [Reading Day], DATEPART(mm,
I.ReadingDate) AS [Reading Month], DATEPART(yyyy, I.ReadingDate) AS [Reading Year]
FROM IntegratedHour_MV90 AS I INNER JOIN
CustRptMeterExtract AS CT ON CT.CustomerName = I.CustomerName
WHERE (I.ReadingDate >= #StartDate) AND (I.ReadingDate <= #EndDate) AND (I.CustomerName IN (#FacilityName))
Expected Result:
SSRS Current Output: Doesnot match
Depending on your layout you could set row grouping to an expression something like this
=SWITCH
(
Parameters!ReportBy.Value=1, Fields!Hour.Value,
Parameters!ReportBy.Value=2, Fields!Day.Value,
Parameters!ReportBy.Value=3, Fields!Month.Value,
Parameters!ReportBy.Value=4, Fields!Year.Value,
True, 0)
This assumes you have already have the hours/days/months/years in your dataset, if not then you would have to replace the field references with expressions to return the relevant month etc.
Based on what I can see above you'll need to add a grouping level for Customer before the group expression. Also, you Quantity expression should be a sum something like this
=SUM(FIelds!IntegratedGeneration.Value)
You may still have a problem though. I'm assuming Price is a unit price, so it does not make sense to sum that too. To get round this, you should calculate the LineValue (Qty * Price) in your dataset then change the price expression to be something like
=(SUM(FIelds!LineValue.Value)/SUM(Fields!IntegratedGeneratio‌​n.Value))
and this will give you the average price.
However, this may be slow and personally I would do the work in your dataset. Again assuming you have the months, years in your table then you could do something like this.
--DECLARE #ReportBy int = 1 -- uncomment for testing
select
MeterID, Price
, CASE #ReportBy
WHEN 1 THEN [Month]
WHEN 2 THEN [Year]
ELSE NULL
END AS GroupByColumn
INTO #t
from dbo.MyDataTable
SELECT
GroupByColumn
, SUM(Price) as Price
FROM #t
Group BY GroupByColumn
Order by GroupByColumn
This assumes your report parameter is called ReportBy, if not just swap the name out.

How to create a dynamic where clause in sql?

So I have created a table that has the following columns from a transaction table with all customer purchase records:
1. Month-Year, 2.Customer ID, 3. Number of Transactions in that month.
I'm trying to create a table that has the output of
1. Month-Year, 2. Number of active customers defined by having at least 1 purchase in the previous year.
The code that I have currently is this but the case when obviously only capturing one date and the where clause isn't dynamic. Would really appreciate your help.
select month_start_date, cust_ID,
(case when month_start_Date between date and add_months(date, -12) then count(cust_ID) else 0 end) as active
from myserver.mytable
where
month_start_Date>add_months(month_start_date,-12)
group by 1,2
EDIT: I'm just trying to put a flag next to a customer if they are active in each month defined as having at least one transaction in the last year thanks!
You might use Teradata's proprietary EXPAND ON synax for creating time series:
SELECT month_start_date, COUNT(*)
FROM
( -- create one row for every month within the next year
-- after a customer's transaction
SELECT DISTINCT
BEGIN(pd) AS month_start_date,
cust_ID
FROM myserver.mytable
EXPAND ON PERIOD(month_start_date, ADD_MONTHS(month_start_date,12)) AS pd
BY ANCHOR MONTH_BEGIN -- every 1st of month
FOR PERIOD (DATE - 500, DATE) -- use this to restrict to a specific date range
) AS dt
GROUP BY month_start_date
ORDER BY month_start_date

SQL: select datetime values prior to that date based on it's value

I want to select rows for a field MRD which is declared as date where it is prior for that date only.
So
(case when sum (transPoints) > 4 and MRD is that same date then 4
So if a row has a date of today, I want the case when to be triggered when the transaction points are bigger than 4 against all columns with the same date.
As you can imagine the date field will be different against many rows.
Based on what I can understand from your question, it seems that the GROUP BY clause may be what you're looking for. If your date column is in the correct format then you may have to use something like:
SELECT CAST(DateColumn as DATE)
FROM YourTable
GROUP BY CAST(DateColumn as DATE)