How to join Year and week column with week dates column - sql-server

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.

Related

Creating Attendance Report with SSRS

I am trying to create a Attendance result set in SQL Server for using it in a SSRS report. The Employee Attendance table is as below:
EmpId
ADate
In
Out
1
2023-01-01
8:00
15:00
I need to calculate the Total working days for all months in a year and display the number of working days per employee. Report format should be as follows:
Saturday and Sunday being weekend, I can able to get the no of working days monthly.
Another table tbl_Holiday has entries for holidays Fromdate and ToDate. I need to consider that also when calculating working days. Several number of results i got from the internet for calculating this. But when creating a view using this data , it has to calculate workdays for each employee row
SELECT
EmpName, EmpId,
(SELECT COUNT(*) FROM tbl_EmpAttendance
WHERE EmpRecId = A.RecId
GROUP BY MONTH(Adate), YEAR(Adate)) AS WorkedDays,
dbo.fn_GetWorkDays(DATEFROMPARTS(YEAR(ADate), MONTH(ADate), 1), EOMONTH(ADate)) AS workingDays
FROM
tbl_Employee A
LEFT JOIN
tbl_EmpAttendance B ON A.RecId = B.EmpRecId
fn_GetWorkDays - calculates the working days for month.
I need to get number of holidays from tbl_holiday too, I understand that this query is becoming more complex than I thought. There must be simpler way to achieve this, can anyone please help?
I tried to get the result in one single view, for using that as SSRS report dataset

Count by days, with all days

I need to count records by days, even if in the day were no records.
Count by days, sure, easy.
But how i can make it to print information, that 'in day 2018-01-10 was 0 records)
Should I use connect by level? Please, any help would be good. Can't use plsql, just oracle sql
First you generate every date that you want in an inline view. I chose every date for the current year because you didn't specify. Then you left outer join on date using whichever date field you have in that table. If you count on a non-null field from the source table then it will count 0 rows on days where there is no join.
select Dates.r, count(tablename.id)
from (select trunc(sysdate,'YYYY') + level - 1 R
from dual
connect by level <= trunc(add_months(sysdate,12),'YYYY') - trunc(sysdate,'YYYY')) Dates
left join tablename
on trunc(tablename.datefield) = Dates.r
group by Dates.r

SQL Join two "month" tables the fastest way?

I have a View called LOGS2016 that is created from 12 individual "Month" tables of naming convention: LOG201601, LOG201602, and so on..
To do normal date range lookups, I'll typically select all records from LOGS2016 and do a DATEADD function on each record. Obviously not the fastest method.
My filter is only ever attempting to find "previous 30 days worth of activity from today", so what I'd like to do is use only 2 tables to cover this query, as opposed to the entire year VIEW which is 12 tables worth of records.
Is there a way to do a join or union on the current month's table and the previous month's table instead of using the annual VIEW? (I can get current year and month using PHP if necessary)
What I've tried (and is still very slow):
-- This takes 11 Seconds
SELECT * FROM LOG201612 WITH (NOLOCK)
UNION ALL
SELECT * FROM LOG201701 WITH (NOLOCK)

SQL Server: selecting a year of account based on a specific date and a date range

I need to apportion some values to a financial year that begins on the 1st December and ends on the 30th November each year.
The rows that contain the value fields are in a table (TABLE A) that has a reference number and an incident date
Table A
ReferenceNumber, Value, IncidentDate
1, 10.00, 01/12/14
2, 15.00, 10/05/13
3, 20.00, 14/10/13
TABLE A is the joined to TABLE B which also has the reference number and contains transactional data including a start date field. Each reference number may have several transactions with different start date values and the aim is to ensure the row selected from TABLE B is the one where the start date is the most recent start date before the incident date from table A
TABLE B
ReferenceNumber, StartDate
1, 01/05/14
1, 01/05/15
2, 12/04/14
2, 12/04/15
3, 05/06/14
3, 04/06/15
TABLE C is a time table that apportions specific dates to financial years.
TABLE C
Date, FinancialYear
30/11/14, FY2013/14
01/12/14, FY2014/15
I am trying to construct a query which joins table A to table B on the Reference number and incident date to start date as described above and then adds the FinancialYear value based on the start date from Table B.
I am struggling to get this to return the correct financial year.
In addition, the data quality is poor so there are many examples where the Incident date from table A is greater than the scope of the financial year selected based on the start date from table B.
I need to be able to return either the appropriate financial year based on start date or, failing that, the financial year corresponding to the incident date
Here is the code I currently have:
SELECT a.ReferenceNumber,
b.StartDate,
c.FinancialYear
FROM dbo.TableA a
INNER JOIN dbo.TableB b
ON a.ReferenceNumber = b.ReferenceNumber
AND b.StartDate = (SELECT MIN(StartDate) FROM dbo.TableB WHERE a.IncidentDateTime > StartDate AND ReferenceNumber = a.ReferenceNumber)
INNER JOIN dbo.Calendar c
ON rdc.PolicyStartDate = c.[Date]
select
a.ReferenceNumber,
min(Value) as Value,
min(IndicentDate) as IncidentDate,
max(StartDate) as StartDate /* others are dummy aggregates but this one is not */
'FY'
+ cast(year(dateadd(month, -11, min(IncidentDate))) as char(4))
+ '/'
+ cast(year(dateadd(month, -11, min(IncidentDate))) - 1999 as char(2)) as FY
from
TableA a cross apply
(
select * from TableB b
where b.ReferenceNumber = a.Reference.Number and b.StartDate < a.IncidentDate
) b
group by a.ReferenceNumber
Your fiscal year starts eleven months "late" so it's easy to determine where a date falls without a lookup.
year(dateadd(month, -11, <date>))
Getting it to match your "FY2013/14" format takes a little extra work but you could write little functions to do these kinds of calculations. By the way, the 1999 comes from adding 1 and subtracting 2000 to get a two-digit year value. Could use modulo 100 to make it generic beyond the year 2098 if that's important.
My assumptions going in:
IncidentDate and StartDate are datatype "DATE". This should also work if they are DATETIME with all time values set the same.
TableC contains a row for every possible date (which is what you implied). Another style would be {FinancialYear, FirstDate, LastDate}, and you'd join to this table using between in the on clause.
I didn't quite get what you meant regarding "the data quality is poor". This query will pull back the desired IncidentDate and StartDate
(if available), allowing you to apply business logic to them. My sample here is "if there is no applicable StartDate, base the FinancialYear on IncidentDate. (Replace those outer joins with inner joins if the data permits it.)
Toss in parameters if you dont' want this data for all ReferenceNumbers.
Check for syntax errors, I couldn't run and test this query.
(Note that "Date" is a confusing name for a column.)
WITH ctePart1 (ReferenceNumber, IncidentDate, ClosestStartDate)
as (-- Data based on the join to "most recent prior StartDate"
select
ta.ReferenceNumber
,ta.IncidentDate
,max(tb.StartDate)
from TableA ta
left outer join TableB tb
on tb.ReferenceNumber = ta.ReferenceNumber
and tb.StartDate < ta.IncidentDate
group by
ta.ReferenceNumber
,ta.IncidentDate)
select
cte.ReferenceNumber
,cte.IncidentDate
,cte.ClosestStartDate
,isnull(tcStart.FinancialYear, tcIncident.FinancialYear) FinancialYear
from ctePart1 cte
left outer join TableC tcStart
on tcStart.Date = cte.ClosestStartDate
left outer join TableC tcIncident
on tcIncident.Date = cte.IncidentDate

Index on Date field in Calendar table

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.

Resources