On a datawarehouse project with SSIS/SSAS, I have to generate my own time dimension because I've personal data to integrate with.
My problem is with SSAS because I also need to integrate translation. After reading the documentation, I've found a command to set language for the current session by using SET LANGUAGE ENGLISH but I'm not able to change language for different field of the query.
Is there a way to generate MONTH_NAME in French and also get MONTH_NAME_DE in German ?
Here is the script that I've found on Internet
WITH Mangal as
(
SELECT Cast ('1870-01-01' as DateTime) Date --Start Date
UNION ALL
SELECT Date + 1
FROM Mangal
WHERE Date + 1 < = '2015-12-31' --End date
)
SELECT
Row_Number() OVER (ORDER BY Date) as ID
, Date as DATE_TIME
, YEAR (date) as YEAR_NB
, MONTH (date) as MONTH_NB
, DAY (date) as DAY_NUMBER
, DateName (mm, date) as MONTH_NAME
, LEFT ( DateName (mm, date), 3) KMONTH_NAME
, DateName (dw, date) as DAY_NAME
, LEFT (DateName (dw, date), 3) as KDAY_NAME
, (SELECT TOP 1 FIELD
FROM TABLEXY
WHERE Date BETWEEN TABLEXY.DATE_FROM AND LEGISLATUR.DATE_TO
AND LANGAGE = 'FR'
) as PERSONAL_FIELD
, (SELECT TOP 1 FIELD
FROM TABLEXY
WHERE Date BETWEEN TABLEXY.DATE_FROM AND LEGISLATUR.DATE_TO
AND LANGAGE = 'DE'
) as PERSONAL_FIELD_DE
FROM Mangal
OPTION (MAXRECURSION 0)
SQL Server has a table containing names of Months and week days. However, they are stored as comma delimited values:
select
months,
shortmonths,
days
from
master.dbo.syslanguages
where
alias in ('English','French', 'German')
You might use this in your query.
Related
I am trying to insert data from a staging table into original table for a particular time period in Microsoft SQL Server Management Studio 18 using below query.
INSERT INTO dbo.trial ([turbineid], [createddate], [lastupdatedby],[lastupdateddate])
SELECT
[turbineid], [createddate], [lastupdatedby], [lastupdateddate]
FROM
dbo.trial_January
WHERE
createddate BETWEEN (DATEPART(mm, createddate) = 01
AND DATEPART(dd, createddate) = 01))
AND (DATEPART(mm, createddate) = 01
AND DATEPART(dd, createddate) = 30)
When trying to execute this query, I get this error:
Incorrect syntax near '='.
You are trying to compare a date with some integers.
Your where clause should look more like this
WHERE createddate BETWEEN (DATEFROMPARTS(DATEPART(YY,createddate),1,1)) AND (DATEFROMPARTS(DATEPART(YY,createddate),1,30))
This claus doesn't make sense
where createddate between
(DATEPART(mm , createddate) = 01 AND DATEPART(dd, createddate) = 01))
AND (DATEPART(mm, createddate) = 01 AND DATEPART(dd, createddate) = 30)
Between state needs two date to check if the given date is between two dates.
for exemple :
SELECT 'true' WHERE GETDATE() BETWEEN GETDATE() -1 AND GETDATE() + 1
And the DATEPART(mm, CreatedDate) returns the month of your date.
SELECT 'true' where DATEPART(mm , GETDATE()) = 10 //Checks if the month of the given date is 10.
According your query, you want to get records of january. So you can try this
INSERT INTO dbo.trial ([turbineid], [createddate], [lastupdatedby],[lastupdateddate])
SELECT
[turbineid], [createddate], [lastupdatedby], [lastupdateddate]
FROM
dbo.trial_January
WHERE
DATEPART(MONTH, createddate) = 01
AND DATEPART(YEAR, createddate) = 2020 -- the year you want
your where condition is not correct
where DATEPART(mm , createddate) = 1
gives you results for first month. you dont need to have anything else for the day if your intention is to look for whole january
basically trying to create a query that will display employee anniversary dates for upcoming month or year of current date, also would like to display a column that shows the years of service
SELECT
Employee,
Hire_Date
CASE WHEN DATEADD(YY,DATEDIFF(yy,Hire_Date,GETDATE()),Hire_Date)<GETDATE() THEN DATEDIFF(yy,Hire_Date,GETDATE())
ELSE DATEDIFF(yy,Hire_Date,GETDATE())-1 END AS 'Years of service'
FROM
MyTable
looking to display employees with anniversary dates coming up in the coming month or in the next year
Here is the script validated (see pciture below) to display the employees with birth_date coming in the next month
Replace mytable by your own table
declare #mytable as table(employe varchar(100), birth_date datetime,hire_date datetime)
insert into #mytable values
('name1','01/01/1972','01/01/2000') ,
('name2','12/02/1985','01/02/2003') ,
('name3','04/12/1990','03/04/2005') ,
('name4','05/03/1969','12/12/2005') ,
('name5','04/02/1968','12/02/2010') ,
('name6','04/04/1968','12/11/2009') ,
('name7','12/03/1978','01/01/2019') ,
('name8','01/12/2000','03/02/2018') ,
('name9','12/12/1970','05/02/2019') ,
('name10','04/04/1980','04/04/2018')
select employe,birth_date,hire_date,
CASE WHEN DATEADD(YY,DATEDIFF(yy,Hire_Date,GETDATE()),Hire_Date)<GETDATE() THEN DATEDIFF(yy,Hire_Date,GETDATE())
ELSE DATEDIFF(yy,Hire_Date,GETDATE())-1 END AS 'Years of service'
from #mytable where (
month(getdate()) < 12
and
month(birth_date)=1+month(getdate()) )
or (month(getdate())=12 and month(birth_date)=1)
I don't understand well, but, if you need know who make anniversary in the next month, or next year, you should use DATEDIFF function for to filter the data.
Example:
SELECT Employee, Hire_Date, DATEDIFF(year, Hire_Date, getdate()) as YearsService
FROM MyTable
-- if you need fetch to next month, you should use <= 1
WHERE DATEDIFF(month, CONCAT(YEAR(GETDATE()), '-', MONTH(Hire_Date), '-' , DAY(Hire_Date)), GETDATE()) = 1
I've tried searching without much luck. What I'm looking to do is based on any input date, get two most recent dates that had the same day of the month and same weekday as the input date.
For example, date of 02/07/2018 (dd/mm/yyyy) should return 02/04/2018 and 02/10/2017 as they were both Monday the 2nd and were two most recent occurrences.
I have a date table I can work with, I was considering doing a join on itself to get this but I'd appreciate some help.
EDIT: Forgot to mention I'm using SQL Server 2012
Your date table needs to have calculated the day of the week (the number) for each day. Then it's just a simple matter of JOINing, sorting and picking the top 2 rows.
SQL Fiddle
MS SQL Server 2017 Schema Setup:
SETUP THE DATE TABLE
/********************************CALENDAR********************************/
/*
As always, thank you to Aaron Bertrand for the Calendar Table example.
https://www.mssqltips.com/sqlservertip/4054/creating-a-date-dimension-or-calendar-table-in-sql-server/
*/
SET DATEFIRST 7 ; /* SUNDAY */ /* Make sure the week starts on the same day. */
CREATE TABLE datedim (
theDate date PRIMARY KEY
, theDay AS DATEPART(day, theDate) --int
, theWeek AS DATEPART(week, theDate) --int
, theMonth AS DATEPART(month, theDate) --int
, theYear AS DATEPART(year, theDate) --int
, theDOW AS DATEPART(weekday, theDate) --int
, yyyymmdd AS CONVERT(char(8), theDate, 112) /* yyyymmdd */
) ;
/************************************************************************/
/*
Use the catalog views to generate as many rows as we need. This example
creates a date dimension for 1 Sept 2017 to 1 Aug 2018.
*/
INSERT INTO datedim ( theDate )
SELECT d
FROM (
SELECT d = DATEADD(day, s1.rn - 1, '2017-01-01')
FROM
(
SELECT TOP ( DATEDIFF(day, '2017-01-01', '2018-12-31') )
rn = ROW_NUMBER() OVER (ORDER BY sao.object_id)
FROM sys.all_objects sao
) s1
) s2
/************************************************************************/
SETUP TEST DATA
/* TEST DATA */
CREATE TABLE t1 (id int identity, testDate date) ;
INSERT INTO t1 ( testDate )
VALUES
( '2018-04-02' ) /* This */
, ( '2017-10-02' ) /* This */
, ( '2018-04-02' ) /* Duplicate */
, ( '2017-09-27' )
, ( '2018-07-01' )
, ( '2018-05-02' ) /* Same day, Diff DOW */
, ( '2017-09-02' ) /* Same day, Diff DOW */
, ( '2017-10-09' ) /* Diff day, Same DOW */
, ( '2017-01-02' ) /* Same day, Same DOW, Earlier */
, ( null )
;
I added a couple of cases that will get picked up in the early filters but get filtered out by the end. See the notes in the setup.
Main Query:
DECLARE #enteredDate date = '2018-07-02' /* This is the date you entered. */
SELECT TOP 2 s1.testDate
FROM (
SELECT t1.testDate
, ROW_NUMBER() OVER ( PARTITION BY t1.testDate ORDER BY t1.testDate DESC, t1.id DESC ) AS rn
FROM t1
INNER JOIN datedim dd ON t1.testDate = dd.theDate
AND dd.theDay = DATEPART(day,#enteredDate)
AND dd.theDOW = DATEPART(weekday,#enteredDate)
) s1
WHERE rn = 1 /* Get 1st result for a date. */
ORDER BY s1.testDate DESC
In the main query, the first thing we do is use the ROW_NUMBER() window function to make sure we only get one record if there are duplicate date entries. If your data is guaranteed to not have dupe dates, you can skip this step.
[Results][2]:
| testDate |
|------------|
| 2018-04-02 |
| 2017-10-02 |
I think this problem is an excellent example of how useful a Calendar Table can be.
If you have a dates table, then you can use it. The following pseudo-code based on ANSI SQL functions, because date functions depend on the database:
select d.*
from dates d
where extract(dow from d.date) = extract(dow from date '2018-07-02') and
extract(day from d.date) = extract(day from '2018-07-02') and
d.date < date '2018-07-02'
order by d.date desc
fetch first 2 rows only;
This may be the dumbest question, but I have a column called [Start Time] which is (datetime, not null) and outputs data in the form '2016-05-25 00:12:01.977'
What I want is to snip everything except the Month and Year and group data into months. What I used is
select format([Start Time],'MMM/yyyy') as [Month]
Which worked fine except that it seems now no longer to be a datetime field and when I add
order by format([Start Time],'MMM/yyyy')
It puts the months in alphabetical order rather than Jan Feb etc. I tried using
convert(date,format([Start Time],'MMM/yyyy'))
but that brought back the error
Msg 241, Level 16, State 1, Line 1 Conversion failed when converting
date and/or time from character string.
Can anyone tell me if it is possible to maintain the date data type when formatting and grouping by month and if so how?
Thanks
Handling dates in SQL Server require a little bit work, but you can get around your problem by changing the dates first to the 1st of the month, grouping with that, and then finally format it, something like this:
select
format(Month2,'MMM/yyyy') as Month,
amount
from
(
select
DATEADD(month, DATEDIFF(month, 0, [Start Time]), 0) as Month2,
sum(amount) as amount
from
yourtable
group by
DATEADD(month, DATEDIFF(month, 0, [Start Time]), 0)
) X
order by
Month2
Format is also quite heavy operation, you should consider using convert or datepart if you have a lot of rows.
select format([Start Time],'MMM/yyyy') as [Month]
order by month([Start Time]), year([Start Time])
Can you check this :
Declare #t table(dtvalue datetime)
insert into #t values ('2016-05-01 00:12:01.977'), ('2016-05-06 00:12:01.977'), ('2016-05-10 00:12:01.977'), ('2016-05-15 00:12:01.977'),
('2016-05-25 00:12:01.977'), ('2016-06-25 00:12:01.977'), ('2016-06-28 00:12:01.977')
--select * from #t
select dtvalue,
format(dtvalue,'MMM/yyyy')
from #t
group by dtvalue
insert into #t values ('2016-05-02 00:12:01.977')
select dtvalue,
format(dtvalue,'MMM/yyyy')
from #t
group by dtvalue
/*Count the record in a month via grouping*/
select count (format(dtvalue,'MMM/yyyy')),
format(dtvalue,'MMM/yyyy')
from #t
group by format(dtvalue,'MMM/yyyy')
I have a table in MSSQL with the following structure:
PersonId
StartDate
EndDate
I need to be able to show the number of distinct people in the table within a date range or at a given date.
As an example i need to show on a daily basis the totals per day, e.g. if we have 2 entries on the 1st June, 3 on the 2nd June and 1 on the 3rd June the system should show the following result:
1st June: 2
2nd June: 5
3rd June: 6
If however e.g. on of the entries on the 2nd June also has an end date that is 2nd June then the 3rd June result would show just 5.
Would someone be able to assist with this.
Thanks
UPDATE
This is what i have so far which seems to work. Is there a better solution though as my solution only gets me employed figures. I also need unemployed on another column - unemployed would mean either no entry in the table or date not between and no other entry as employed.
CREATE TABLE #Temp(CountTotal int NOT NULL, CountDate datetime NOT NULL);
DECLARE #StartDT DATETIME
SET #StartDT = '2015-01-01 00:00:00'
WHILE #StartDT < '2015-08-31 00:00:00'
BEGIN
INSERT INTO #Temp(CountTotal, CountDate)
SELECT COUNT(DISTINCT PERSON.Id) AS CountTotal, #StartDT AS CountDate FROM PERSON
INNER JOIN DATA_INPUT_CHANGE_LOG ON PERSON.DataInputTypeId = DATA_INPUT_CHANGE_LOG.DataInputTypeId AND PERSON.Id = DATA_INPUT_CHANGE_LOG.DataItemId
LEFT OUTER JOIN PERSON_EMPLOYMENT ON PERSON.Id = PERSON_EMPLOYMENT.PersonId
WHERE PERSON.Id > 0 AND DATA_INPUT_CHANGE_LOG.Hidden = '0' AND DATA_INPUT_CHANGE_LOG.Approved = '1'
AND ((PERSON_EMPLOYMENT.StartDate <= DATEADD(MONTH,1,#StartDT) AND PERSON_EMPLOYMENT.EndDate IS NULL)
OR (#StartDT BETWEEN PERSON_EMPLOYMENT.StartDate AND PERSON_EMPLOYMENT.EndDate) AND PERSON_EMPLOYMENT.EndDate IS NOT NULL)
SET #StartDT = DATEADD(MONTH,1,#StartDT)
END
select * from #Temp
drop TABLE #Temp
You can use the following query. The cte part is to generate a set of serial dates between the start date and end date.
DECLARE #ViewStartDate DATETIME
DECLARE #ViewEndDate DATETIME
SET #ViewStartDate = '2015-01-01 00:00:00.000';
SET #ViewEndDate = '2015-02-25 00:00:00.000';
;WITH Dates([Date])
AS
(
SELECT #ViewStartDate
UNION ALL
SELECT DATEADD(DAY, 1,Date)
FROM Dates
WHERE DATEADD(DAY, 1,Date) <= #ViewEndDate
)
SELECT [Date], COUNT(*)
FROM Dates
LEFT JOIN PersonData ON Dates.Date >= PersonData.StartDate
AND Dates.Date <= PersonData.EndDate
GROUP By [Date]
Replace the PersonData with your table name
If startdate and enddate columns can be null, then you need to add
addditional conditions to the join
It assumes one person has only one record in the same date range
You could do this by creating data where every start date is a +1 event and end date is -1 and then calculate a running total on top of that.
For example if your data is something like this
PersonId StartDate EndDate
1 20150101 20150201
2 20150102 20150115
3 20150101
You first create a data set that looks like this:
EventDate ChangeValue
20150101 +2
20150102 +1
20150115 -1
20150201 -1
And if you use running total, you'll get this:
EventDate Total
2015-01-01 2
2015-01-02 3
2015-01-15 2
2015-02-01 1
You can get it with something like this:
select
p.eventdate,
sum(p.changevalue) over (order by p.eventdate asc) as total
from
(
select startdate as eventdate, sum(1) as changevalue from personnel group by startdate
union all
select enddate, sum(-1) from personnel where enddate is not null group by enddate
) p
order by p.eventdate asc
Having window function with sum() requires SQL Server 2012. If you're using older version, you can check other options for running totals.
My example in SQL Fiddle
If you have dates that don't have any events and you need to show those too, then the best option is probably to create a separate table of dates for the whole range you'll ever need, for example 1.1.2000 - 31.12.2099.
-- Edit --
To get count for a specific day, it's possible use the same logic, but just sum everything up to that day:
declare #eventdate date
set #eventdate = '20150117'
select
sum(p.changevalue)
from
(
select startdate as eventdate, 1 as changevalue from personnel
where startdate <= #eventdate
union all
select enddate, -1 from personnel
where enddate < #eventdate
) p
Hopefully this is ok, can't test since SQL Fiddle seems to be unavailable.