Why does the below code not work when I use the alias 'enddates' in the datediff (It throws up the error 'invalid column name: enddates')?
It works if I use the alias without the datediff (i.e. just ordering by enddates)
It also works if I copy the whole enddates formula into the datediff. But why can't I use the alias in the datediff? Thought the whole point of an alias is you can refer to it to shorten the code.
I did see something similar posted before, but there wasn't an answer
p.start_date,
(
select min(p2.end_date) pend_date from projects p2
where p2.end_date not in
(select start_date from projects p3) and p2.end_date > p.start_date
) enddates
from projects p
where p.start_date not in
(select end_date from projects)
order by datediff(day, start_date,enddates), start_date```
Related
I've been searching for a good generate_series analog in Snowflake but what I've found so far is a bit limiting in scope. Most of the examples I've seen use rowcount but I need something more dynamic than that.
I have these columns:
location_id, subscription_id, start_date, end_date
The datediff of the date columns is usually a year but there are many instances where it isn't so I need to account for that.
How do I generate a gapless date range between my start and end dates?
Thank you!
There are several ways to approach this, but here's the way I do it with SQL Generator function Datespine_Groups.
The reason I like to do it this way, is because its flexible enough that I can add weekly, hourly, or monthly intervals between the dates and reuse the code.
The parameter group bounds changes the way the join happens in a subtle way that allows you to control how the dates get filtered out:
global - every location_id, subscription_id combination will start on the same start_date
local - every location_id, subscription_id has their own start/end dates based on the first and last values in the date column
mixed - every location_id, subscription_id has their own start/end dates, but they all share the same end date
Rather than try and make it perfect in 1 query, I think it's probably easier to generate it with mixed and then filter out where the group_start_date occurs after the end_date of your original data.
Here's the SQL. At the very beginning you can either (1) find a way to dynamically generate the 3 parameters, or (2) hard code a ridiculous range that'll last your career and let the rest of the query filter them out :)
You can change month to another datepart, I only assumed you were looking for monthly.
WITH GLOBAL_SPINE AS (
SELECT
ROW_NUMBER() OVER (
ORDER BY
NULL
) as INTERVAL_ID,
DATEADD(
'month',
(INTERVAL_ID - 1),
'2018-01-01T00:00' :: timestamp_ntz
) as SPINE_START,
DATEADD(
'month', INTERVAL_ID, '2018-01-01T00:00' :: timestamp_ntz
) as SPINE_END
FROM
TABLE (
GENERATOR(ROWCOUNT => 2192)
)
),
GROUPS AS (
SELECT
location_id,
subscription_id,
MIN(start_date) AS LOCAL_START,
MAX(start_date) AS LOCAL_END
FROM
My_First_Table
GROUP BY
location_id,
subscription_id
),
GROUP_SPINE AS (
SELECT
location_id,
subscription_id,
SPINE_START AS GROUP_START,
SPINE_END AS GROUP_END
FROM
GROUPS G CROSS
JOIN LATERAL (
SELECT
SPINE_START,
SPINE_END
FROM
GLOBAL_SPINE S
WHERE
S.SPINE_START >= G.LOCAL_START
)
)
SELECT
G.location_id AS GROUP_BY_location_id,
G.subscription_id AS GROUP_BY_subscription_id,
GROUP_START,
GROUP_END,
T.*
FROM
GROUP_SPINE G
LEFT JOIN My_First_Table T ON start_date >= G.GROUP_START
AND start_date < G.GROUP_END
AND G.location_id = T.location_id
AND G.subscription_id = T.subscription_id
How do I use GETDATE() in a WHERE clause using single quotes? I have the following script:
SELECT DISTINCT
pm_requisition.a_requisition
,pm_requisition.a_req_description
,pm_requisition.rq_position_loc
,pm_requisition.rq_status_of_emp
,pm_applicant_rec.a_applicant_no
,pm_applicant_rec.aq_status_of_appl
,pm_applicant_rec.aq_apply_date
FROM
pm_requisition
LEFT OUTER JOIN pm_applicant_rec
ON pm_requisition.a_requisition = pm_applicant_rec.a_requisition
WHERE
pm_requisition.rq_status_of_req NOT IN (N'6', N'7')
AND pm_applicant_rec.aq_status_of_appl = N'N'
AND rq_position_loc = '3300'
AND pm_applicant_rec.aq_apply_date = CAST(GETDATE()AS datetime2) --('2021-03-30 00:00:00.000')
The dataset does not yield any data using the GETDATE() clause, but if I use today's date (commented out) with single quotes I get the correct dataset. I obviously can't put single quotes around CAST(GETDATE()AS datetime2). Am I missing something simple?
The reason your query does not work is that GETDATE() returns the current date and time, not the current date. As a result, the last line will never match, as you are comparing a date only with a date and time.
Your solution CAST(GETDATE() AS DATE) works is because it removes the time, which means you are now comparing a date with a date.
If you simplify your SQL to something like this :-
SELECT TOP 1 aq_apply_date,
GETDATE() [GETDATE]
FROM pm_applicant_rec;
you will see a result like this, so two different values, and clear why they do not match :-
aq_apply_date GETDATE
----------------------- -----------------------
2021-04-04 00:00:00.000 2021-04-04 14:32:15.507
You might see something slightly different depending on the datatype used for aq_apply_date.
My business intelligence tool is creating a lot of issues with calculating a variance YOY, instead, I am contemplating creating a view in my Database which will allow me to subtract two columns giving me the variance.
I am trying to wrap my head around the best way to go about this, been testing datepart, convert, cast on the date but I am sure I am going the wrong way about this.
select top 1
Business_date,
CONCAT(DATEPART(MM, Business_Date),'-', DATEPART(DD, Business_Date)) as
DayMonth,
case
when DATEPART(YYYY, Business_Date) = '2019' then 2019
end
from Occupancy_Forecast;
I know the code above does not give me anything where i need to be as I am trying to see the best way to do this, what I am looking for is something like the attached screenshot:
I have also included a screenshot of the current table I am reading from so you understand the current format
Using #Larnu statement regarding the pivot I have been able to create a view stored containing the data required using the below to give me the desired output:
select Resort as Resort, Business_Date as Date, [2016], [2017], [2018], [2019],
[2020]
from
(select Resort, business_date, DATEPART(YYYY, Business_Date) as Year, ADR
from Occupancy_Forecast
where Business_Date > '2015-12-31') as SourceTable
PIVOT
(
AVG(ADR)
FOR YEAR IN ([2016], [2017], [2018], [2019], [2020] )
) as PivotTable
I have column Terms in my table and it contains data like this:
30D, 40D, etc.
D represents days.
My question: how can I sum date in Terms column? How can I convert string to int?
Thank you in advance.
Just use REPLACE to ditch the D and CONVERT to convert the varchar to a number....
SELECT SUM(CONVERT(int, REPLACE(Terms,'D',''))) FROM TableName
Edit: Commentor is right, CAST would work too.
And I dont get all the down votes. The guy's just asking a SQL question.
Jeez... Tough crowd.
Edit2:
OK, based on comments, it seems like you would like to get a "due date" from the terms (say, TODAY + 30D or "today + 30 days"). To do that, we'd need a DATE column. OR, we can just use today's date (GETDATE())
Assume your table has a date column called ... dt
The SQL to pull dt+'30D' would require us to add 30 "days" to dt.
DATEADD will add days, and the aforementioned CONVERT+REPLACE combo will convert '30D' to just plain '30' ...
So, you end up with the following SQL:
SELECT DATEADD(day, CONVERT(int, REPLACE(Terms,'D','')), dt) FROM TableName
The 'day' tells DATEADD to add days (that seems really obvious ... now),
the CONVERT+REPLACE tells it how many days to add
AND - dt is our column name.
SO - how about just adding "30D" to TODAY? Easy. We just swap out dt with GETDATE() ...
SELECT DATEADD(day, CONVERT(int, REPLACE(Terms,'D','')), GETDATE()) FROM TableName
SELECT AVG(SALARY) - AVG(CONVERT(int, REPLACE(SALARY,'0','')))
FROM EMPLOYEES;
I am trying to create a simple indexed view on the query below. But when I try to create a unique clustered index on it, I get the following error:
Cannot create the clustered index '..' on view '..' because the select
list of the view contains an expression on result of aggregate
function or grouping column. Consider removing expression on result of
aggregate function or grouping column from select list.
The query I used is as follows:
SELECT
[Manufacturer]
,ISNULL(SUM([QAV]),0) as AvgQAV
,ISNULL(SUM([BackOrders$]),0)as AvgBackorder$
,DATEPART(year,[Date])as Year
,DATEPART(month,[Date])as Month
,[fixSBU]
,[DC Name]
FROM [dbo].[TABLE1]
Group By
[Manufacturer]
,DATEPART(year,[Date])
,DATEPART(month,[Date])
,[fixSBU]
,[DC Name]
Could anyone tell me the possible cause for this?
As you can see I am already using the ISNULL function.
Here is a link to all the restrictions of an index view: https://msdn.microsoft.com/en-us/library/ms191432.aspx#Restrictions
From the documentation these two items should stick out:
If GROUP BY is present, the VIEW definition must contain COUNT_BIG(*)
and must not contain HAVING. These GROUP BY restrictions are
applicable only to the indexed view definition. A query can use an
indexed view in its execution plan even if it does not satisfy these
GROUP BY restrictions.
If the view definition contains a GROUP BY
clause, the key of the unique clustered index can reference only the
columns specified in the GROUP BY clause.
Also, you need to change your ISNULL statements. Right now you have ISNULL(SUM([BackOrders$]),0) and it should be SUM(ISNULL([BackOrders$], 0)). You need to SUM the ISNULL, not the other way around.
Doesn't make a whole lot of sense (at least not to me) but reference: https://msdn.microsoft.com/en-us/library/ms191432.aspx
Specifically:
If GROUP BY is present, the VIEW definition must contain COUNT_BIG(*) and must not contain HAVING. These GROUP BY restrictions are applicable only to the indexed view definition. A query can use an indexed view in its execution plan even if it does not satisfy these GROUP BY restrictions.
try adding a COUNT_BIG(*) to your select list and give it a whirl.
I had a similar problem. One of my select fields looked like this:
sum(Pa * (CTRatio1a/CTRatio2a) * (VTRatio1/VTRatio2)* Polarity * [Percentage])/1000.0
By including the last division by 1000 in the bracket, it resolved the problem:
sum(Pa * (CTRatio1a/CTRatio2a) * (VTRatio1/VTRatio2)* Polarity * [Percentage]/1000.0)
Tip: It's better to have a real date field in the database and not just Year / Month. That way you can create a date index in addition to the clustered index.
However if you have FullDate, Year and Month you can get the same error message view contains an expression on result of aggregate function or grouping column.
That error can occur if you do this:
SELECT
[Manufacturer]
,[Date] as FullDate
,DATEPART(year,[Date]) as Year
,DATEPART(month,[Date]) as Month
,COUNT_BIG(*) as Count
,SUM(OrderValue) as TotalOrderValue
FROM [dbo].[TABLE1]
Group By
[Manufacturer]
,[Date]
,DATEPART(year,[Date])
,DATEPART(month,[Date])
While not immediately obvious what's going on I assume this is because it looks at Date in the grouping columns and finds Date used in other columns (for the year and month). Clearly though this should logically work and you should be able to group like that.
I found a trick that got it working:
SELECT
[Manufacturer]
,DATEADD(day, 0, [Date]) as FullDate
,DATEPART(year,[Date])as Year
,DATEPART(month,[Date])as Month
,COUNT_BIG(*) as Count
,SUM(OrderValue) as TotalOrderValue
FROM [dbo].[TABLE1]
Group By
[Manufacturer]
,DATEADD(day, 0, [Date])
,DATEPART(year,[Date])
,DATEPART(month,[Date])
This tricked the parser into allowing it, and now I can create a separate index (after the clustered) to search by FullDate.
Bonus: The real reason I stumbled upon this was because I needed ISO_WEEK and ISO_YEAR which are expensive to calculate. Here here's my final full list of grouping clauses I'm using for that:
-- date
DATEADD(day, 0, [Order].OrderDateDt) as OrderDateDt, -- trick! add 0 days to date
-- day / month / year / quarter
DATEPART(day, [Order].OrderDateDt) as OrderDate_day,
DATEPART(month, [Order].OrderDateDt) as OrderDate_month,
DATEPART(year, [Order].OrderDateDt) as OrderDate_year,
DATEPART(quarter, [Order].OrderDateDt) as OrderDate_quarter,
-- iso week
DATEPART(iso_week, [Order].OrderDateDt) as OrderDate_isoweek,
YEAR(DATEADD(day, 26 - DATEPART(iso_week, [Order].OrderDateDt), [Order].OrderDateDt)) as OrderDate_isoyear
Make sure to include all these exactly the same in the SELECT and GROUP BY.