Index on Date field in Calendar table - sql-server

I have a calendar table that has a list of all days frtom 01-JAN-1990 to 31-DEC-2050
That results in 22279 rows in my table.
A lot of queries we do, I join to the calendar as I need a list of dates based on certain data. For example:
SELECT ...
FROM Person A
INNER JOIN Calendar C
ON C.DateValue BETWEEN A.StartDate and A.EndDate
This is an example... but I'm looking for a list of the dates for the person, and a date column to come back.
What I'd like to know, is: Is the DateValue column a good candicate for an Index? And would there be ebefit of it being Clustered?
(SQL Server 2008 R2)

No, the Date type columns is not good candidate. Columns which you want to choose should be more simple. like int or BigInt types.

Related

MSSQL, how compare records with dataframe table?

let's say we have a table with invoices and employees ID
and another table for vacation which also contains an employee ID.
In this case only emplyee1 had vacation a these date frames.
Now we have to compare if the invoice date is between or exactly at the date frames of vacation table.
The aim is: The invoice date has to be compared, if an employee is on vacation the calc_flag = 0, if not then always=1. E.g. employee1 was from 2023/01/05 till 2023/01/12 on vacation.
So all his invoices must be calc_flag=0 for this time.
How to create the sql query in mssql for this topic?
Thanks for any advice.
I already tried to check the dateframes but if there are several entries in vacation table, I'm not sure how to handle it.
One way to do this is a LEFT JOIN to check for existance. Perhaps you need to tweak the < or > depening if you would like to include the Begin and or End date.
SELECT i.InvNo,
i.emp_ID,
i.InvDate,
i.calc_flag ,
CASE WHEN v.Emp_ID IS NOT NULL THEN 0 ELSE 1 END AS calc_flage
FROM dbo.invoices AS i
LEFT JOIN dbo.vacation AS v ON v.Emp_ID = i.emp_ID AND v.[Begin] < i.InvDate AND v.[End] > i.InvDate

How to join Year and week column with week dates column

I have these two columns on separate tables:
A column on table 1, which shows the year and the week. There are duplicates as there are different sets of data belonging to each row in this column on the right side of the table, but I have left this out to make the problem clearer:
|.Year Week.|
|..2015 52..|
|..2015 52..|
|..2015 53..|
|..2016 01..|
|....etc....|
|....etc....|
|..2017 23..|
|..2017 23..|
|..2017 23..|
|..2017 24..|
|..2017 25..|
|..2017 25..|
Then there's this column on table 2, which shows chronologically the length of a week as you go down the years in 1-week increments. This is more like a calendar table/database:
|----Week-----|
|080115_140115|
|150115_210115|
|220115_280115|
|.....etc.....|
|.....etc.....|
|090217_150217|
|160217_220217|
|230217_010317|
My question is how do I most efficiently join the weekly column in table 2 with the year week column in table 1 without hard coding any join statements
where [year week] = 'yyyy ww'
etc etc?
I was thinking a joint statement at first but realised I have no common column in both tables.
I have to keep the formats for both tables the same. Was thinking, is there away to extract the weeks from the |year week| column into a separate column then join it that way?
I'm not sure where to begin.
Try extracting the year , week from table 1 using string functions and join with the table 2 year and week. Extract year and week from table 2 as shown below.
year is
select DATEPART( year,CONVERT(DATE,SUBSTRING(SUBSTRING('080115_140115',0,7),5,2) + SUBSTRING(SUBSTRING('080115_140115',0,7),3,2) +SUBSTRING(SUBSTRING('080115_140115',0,7),0,3),102))
week is
select DATEPART( wk,CONVERT(DATE,SUBSTRING(SUBSTRING('080115_140115',0,7),5,2) + SUBSTRING(SUBSTRING('080115_140115',0,7),3,2) +SUBSTRING(SUBSTRING('080115_140115',0,7),0,3),102))
Ok, so this might not be the most efficient answer, but i did a select distinct statement for table 1 then joined table 2 through excel.
Since this is a static/historical table (and i only need to do it once) i imported the template/data from excel into sql again and used year week as the common column to join the two tables.

Date range based on Column Date

I am using the latest SQL Server. I have a table with a CreatedDate column. I need to write a Query that uses dates that are plus or minus 7 from the Date in CreatedDate. I have no clue how to go about this. My thought was this:
DECLARE #Date datetime
DECLARE #SevenBefore datetime
DECLARE #SevenAfter datetime
SET #Date = CreatedDate
SET #SevenBefore = DATEADD(day,-7,#Date)
SET #SevenAfter = DATEADD(day,7,#Date)
SELECT *
FROM <table>
WHERE <table> BETWEEN #SevenBefore AND #SevenAfter
The issue with this is that I cannot use "CreatedDate" as a SET #DATE because SQL gives an error "Invalid column name 'CreatedDate'"
Any help would be appreciated. I cannot list a date because every date in that column could be different.
Thanks
In this case, you need to stop thinking as a programmer would, and start thinking as a Database programmer would.
Lets work only with this central part of your query:
SELECT *
FROM <table>
WHERE <table> BETWEEN #SevenBefore AND #SevenAfter
Now, you say that the CreatedDate is a column in a table. For this example, I will assume that the CreatedDate is in a table other than the one in your example above. For this purpose, I will give two fake names to the tables. The table with the CreatedDate, I will call tblCreated, and the one from the query above I will call tblData.
Looking above, it's pretty obvious that you can't compare an entire table row to a date. There must be a field in that table that contains a date/time value. I will call this column TargetDate.
Given these assumptions, your query would look something like:
SELECT *
FROM tblCreated tc
INNER JOIN tblData td
ON td.TargetDate BETWEEN DATEADD(day, -7, tc.CreatedDate) and DATEADD(day, 7, tc.CreatedDate)
Looking at this, it is clear that you still need some other associations between the tables. Do you only want all data rows per customer based on the Created date, or perhaps only want Creations where some work was done on them as shown in the Data records, or ??. Without a fuller specification, we can't help with that, though.

datediff between multiple records in SQL

I have one scenario where i want to get a count if date difference between the two dates is
<=14 days.That is in first table i have to filter records where any one value of DATE1 values are <=14 days of DATE2.
For Ex:
q1="SELECT DATE1 FROM DATE1_TABLE";
q2="SELECT DATE2 FROM DATE2_TABLE";
My simple query :
SELECT
COUNT(*)
FROM
DATE1_TABLE WHERE DATEDIFF(DD,DATE1,(SELECT DATE2 FROM DATE2_TABLE))<=14
But i have multiple records in both the tables,but i want to choose any record having
this difference then it will get a count >0.So,it is throwing error subquery returned more
than one record.I want some solutions for this.I am using SQL SERVER 2008
NOTE:I can't use join here.because i wanted results from two different queries.
Thanks in advance.
You can use TOP 1 clause in your query..
SELECT TOP 1 *
FROM DATE1_TABLE
WHERE DATEDIFF(DD,DATE1,(SELECT DATE2 FROM DATE2_TABLE))<=14
You cannot use SELECT which will return multiple values where function expects scalar value... however you can join those tables:
SELECT
COUNT(DISTINCT dt1.*)
FROM DATE1_TABLE dt1 INNER JOIN DATE2_TABLE dt2 ON DATEDIFF(DD,DATE1,DATE2)<=14
This query will join tables on values only when they are within 14 days and count on unique values from DATE1_TABLE. I have no idea if is it performance wise.

Creating Calendar

I have created a SSRS report to show holidays that have been booked at a company, on each line it shows date from and date to, is there a way of getting the data to add a line for each day rather than a single line with from and to? as I want to populate a calendar using these fields.
This is regularly solved using a "calendar" table, i.e. a table that has a list of all dates. Then your query looks something like this:
select c.date
from data_table d
inner join
calendar_table c
on c.date between d.start_date and d.end_date
There's an example of how to create a very powerful calendar table here.

Resources