adding a column to a table with different parameters - sql

I am trying to enter 2 tables into one output my problem is that the parameter is pulling from 2 different columns. I need to be able to show what was completed and the work ordered for a months period. I do not get any errors as the script is written but after 3 hours I stopped it from running.
If I change the join on the #Ordered to iAuditID from EffectiveDate it takes a few seconds to run, but it does not pull the correct information then. I only need the count of ordered audits to be correct and in the #data table and correct. Work may have been ordered a few months before it was completed, therefore I need to be able see how much work is coming in each month and what is being completed.
I am using SQL 2008.
DECLARE
#StartDate datetime,
#EndDate datetime,
#iClientID int,
#iServiceLevelID int
SET #StartDate = '1-1-13'
SET #EndDate = '12-30-13'
SET DATEFIRST 7
DECLARE #TB1 TABLE (EffectiveDate datetime,
iAuditID int,
iClientID int,
iServiceLevelID int)
INSERT INTO #TB1
SELECT dateadd(month, datediff(month, 0, a.dtClosedDate),0) AS EffectiveDate,
a.iAuditID, a.iClientID, a.iServiceLevelID
FROM vwtblAudit a
WHERE (a.dtClosedDate >= #StartDate)
AND (a.dtClosedDate <= #EndDate)
AND (a.iClientID = #iClientID OR #iClientID is null)
AND (a.iServiceLevelID = #iServiceLevelID or #iServiceLevelID is null)
GROUP BY dateadd(month, datediff(month, 0, a.dtClosedDate),0),
a.iClientID, a.iAuditID, a.iServiceLevelID
DECLARE #Ordered TABLE (EffectiveDate datetime,
iAuditID int,
iClientID int,
iServiceLevelID int,
dtOpenDate int)
INSERT INTO #Ordered
SELECT dateadd(month, datediff(month, 0, a.dtOpenDate),0) AS EffectiveDate,
a.iAuditID, a.iClientID, a.iServiceLevelID,
Count(a.dtOpenDate) as Ordered
FROM tblAudit a
WHERE (a.dtOpenDate >= #StartDate)
AND (a.dtOpenDate <= #EndDate)
AND (a.iClientID = #iClientID OR #iClientID is null)
AND (a.iServiceLevelID = #iServiceLevelID or #iServiceLevelID is null)
GROUP BY dateadd(month, datediff(month, 0, a.dtOpenDate),0),
a.iClientID, a.iServiceLevelID, a.iAuditID
order by iClientID, EffectiveDate
DECLARE #DATA table(iclientID int,
sClientCode varchar(8),
sClientName varchar(50),
iServiceLevelID int,
sServiceLevelName varchar(50),
EffectiveDate datetime,
iAuditCount int,
Completed int)
SELECT tblClient.iclientID, tblClient.sClientCode, tblClient.sClientName,
tblServiceLevel.iServiceLevelID,
TB1.EffectiveDate, COUNT(*) AS iAuditCount,
COUNT(Ordered.dtOpenDate) as Ordered
FROM #TB1 TB1 INNER JOIN
tblClient ON TB1.iClientID = tblClient.iClientID INNER JOIN
tblServiceLevel ON TB1.iServiceLevelID = tblServiceLevel.iServiceLevelID
join #Ordered Ordered on TB1.EffectiveDate=Ordered.EffectiveDate
GROUP BY tblClient.iClientID, TB1.iServiceLevelID, tblclient.sClientCode,
tblClient.sClientName, tblServiceLevel.iServiceLevelID,
tblServiceLevel.sServiceLevelName, TB1.EffectiveDate
return
SET DATEFIRST 7
Every a from the #data worked like it should, but I was ask to add the work coming in, so I added #ordered table to bring in the correct information. The data is still correct except for the ordered column. See sample below:
clientID ClientCode ClientName iServiceLevelID EffectiveDate iAuditCount Ordered
0001 1001 Sample 1 Jan 2014 104 19(this number should be 134)

Related

How to pass multiple values one by one for a Parameter in an SQL Query and union the results?

I have an SQL Statement which accepts a parameter #EndDate as DateTime. I want to be able to pass several values for #EndDate one by one and then Union the results of all the Queries. I have tried using CTE for this but it is of no use. I want to pass several Dates for #EndDate. Any help would be greatly appreciated.
My Query is:
DECLARE #EndDate as DateTime
SET #EndDate = '2018/02/25'
SELECT
CONVERT(VARCHAR, #EndDate, 101) [R_Date]
,[Name]
[Type]
FROM [dbo].[S_Table]
This is Sample query how u can loop through multiple dates. A while loop should select all rows into one table, do not need to perform union all
DECLARE #table TABLE (
day INT
,Month INT
,DATE DATE
)
DECLARE #startdate DATE = '2018/02/25'
DECLARE #enddate DATE = cast(getdate() AS DATE)
WHILE #startdate <= #enddate
BEGIN
SELECT #startdate = dateadd(dd, 1, #startdate)
INSERT #table (
day
,Month
,DATE
)
SELECT day(#startdate)
,MONTH(#startdate)
,#startdate
END
SELECT *
FROM #table;
In your logic for passing multiple values into query , you can store result set into temporal table, which holds looped records
DECLARE #table TABLE (
[R_Date] DATE
,Name VARCHAR(155)
,Value VARCHAR(155)
)
DECLARE #enddate DATE = '2018/02/25'
DECLARE #enddate1 DATE = cast(getdate() AS DATE)
WHILE #enddate <= #enddate1
BEGIN
SELECT #enddate = dateadd(dd, 1, #enddate)
INSERT #table (
R_Date
,Name
,Value
)
SELECT CONVERT(VARCHAR, #EndDate, 101) [R_Date]
,[Name] [Type]
FROM [dbo].[S_Table]
WHERE DATE = #enddate
-------More filters
END
SELECT *
FROM #table;

SQL using #table/ Temp table inside a table valued function

I need to have a function to get all the week numbers in a given date range.
I have to seperate this from my stored procedure since it has a lengthy process.
But when I use #tables in side the function it gives following error
Msg 2772, Level 16, State 1, Procedure WeekNumbersWithinRange, Line 19
Cannot access temporary tables from within a function.
And here is my function.
CREATE FUNCTION WeekNumbersWithinRange
(
#FromDate DATETIME,
#ToDate DATETIME
)
RETURNS TABLE
AS
BEGIN
IF OBJECT_ID (N'tempdb..#WeeksofRange', N'U') IS NOT NULL
BEGIN
DROP TABLE #WeeksofRange
END
CREATE TABLE #WeeksofRange (WeekNo INT);
-- Get all week numbers for the given delivery date range
IF OBJECT_ID (N'tempdb..#Calendar', N'U') IS NOT NULL
BEGIN
DROP TABLE #Calendar
END
CREATE TABLE #Calendar
(
CalendarDate DATE PRIMARY KEY,
IsWeekend BIT,
YearNo SMALLINT,
QuarterNo TINYINT,
MonthNo TINYINT,
DayOfYearNo SMALLINT,
DayNo TINYINT,
WeekNo TINYINT,
WeekDayNo TINYINT
)
DECLARE #beginDate DATE, #endDate DATE
SELECT
#beginDate = #FromDate, #endDate = #ToDate
WHILE #beginDate <= #endDate
BEGIN
INSERT INTO #Calendar (CalendarDate, IsWeekend, YearNo, QuarterNo, MonthNo, DayOfYearNo, DayNo, WeekNo, WeekDayNo)
SELECT
#beginDate As CalendarDate,
(CASE WHEN DATEPART(Weekday, #beginDate) IN (7, 1)
THEN 1 ELSE 0
END) AS IsWeekend,
DATEPART(Year, #beginDate) AS YearNo,
DATEPART(QUARTER, #beginDate) AS QuarterNo,
DATEPART(MONTH, #beginDate) AS MonthNo,
DATEPART(DayOfYear, #beginDate) AS DayOfYearNo,
DATEPART(Day, #beginDate) AS DayNo,
DATEPART(Week, #beginDate) AS WeekNo,
DATEPART(WEEKDAY, #beginDate) AS WeekDayNo
--,(Case When #beginDate < '02/03/2011' Then 0 Else DATEPART(Week, #beginDate) - 5 End) As mySpecificWeekNo
SET #beginDate = DATEADD(Day, 1, #beginDate)
END
INSERT INTO #WeeksofRange
SELECT DISTINCT WeekNo
FROM #Calendar;
-- End of Select all week numbers in the range
SELECT * FROM #WeeksofRange
GO
Is there any other way to do this? Or do I need to write this logic inside my stored procedure?
You cannot use a Temp table in UDF because
the object can't be created inside UDF.
Instead of using a Temp table, use a table variable, that should solve your problem
CREATE FUNCTION WeekNumbersWithinRange
(
#FromDate DATETIME,
#ToDate DATETIME
)
RETURNS TABLE
AS
BEGIN
DECLARE #WeeksofRange TABLE
(
WeekNo INT
)
-- Get all week numbers for the given delivery date range
declare #Calendar table
(CalendarDate Date Primary key, IsWeekend Bit, YearNo SmallInt, QuarterNo TinyInt, MonthNo TinyInt, DayOfYearNo SmallInt, DayNo TinyInt, WeekNo TinyInt, WeekDayNo TinyInt )
Declare #beginDate Date, #endDate Date
Select #beginDate = #FromDate , #endDate = #ToDate
While #beginDate <= #endDate
Begin
Insert Into #Calendar (CalendarDate, IsWeekend, YearNo, QuarterNo, MonthNo, DayOfYearNo, DayNo, WeekNo, WeekDayNo)
Select
#beginDate As CalendarDate
,(Case When DATEPART(Weekday, #beginDate) In (7, 1) Then 1 Else 0 End) As IsWeekend
,DATEPART(Year, #beginDate) As YearNo
,DATEPART(QUARTER, #beginDate) As QuarterNo
,DATEPART(MONTH, #beginDate) As MonthNo
,DATEPART(DayOfYear, #beginDate) As DayOfYearNo
,DATEPART(Day, #beginDate) As DayNo
,DATEPART(Week, #beginDate) As WeekNo
,DATEPART(WEEKDAY, #beginDate) As WeekDayNo
--,(Case When #beginDate < '02/03/2011' Then 0 Else DATEPART(Week, #beginDate) - 5 End) As mySpecificWeekNo
Set #beginDate = DateAdd(Day, 1, #beginDate)
End
INSERT INTO #calendar
SELECT DISTINCT WeekNo FROM #Calendar;
-- End of Select all week numbers in the range
SELECT * FROM #WeeksofRange
GO
I'd normally choose to make the Calendar table permanent and populate it with, say, a centuries worth of rows. And then just query it.
But, if you have to have this function, you can write it to use a CTE and avoid any explicit state/iteration management:
CREATE FUNCTION WeekNumbersWithinRange
(
#FromDate DATETIME,
#ToDate DATETIME
)
RETURNS TABLE
AS
return (With Weeks as (
select DATEPART(week,#FromDate) as Week,#FromDate as dt
union all
select DATEPART(week,ndt),ndt
from Weeks
cross apply (select DATEADD(day,7,dt) as ndt) t
where
ndt < #ToDate
)
select Week from Weeks
union
select DATEPART(week,#ToDate)
)
I've made the simplifying assumption that week numbers only change every 7 days so we don't need to generate a row for every day inside the CTE. Also, I use the final UNION to make sure that the final week is included. It could be skipped since I'm working in 7 day increments, so we could jump our value straight from a previous week to a value greater than #ToDate.
Depending on the ranges you're working with, you may have to apply the MAXRECURSION option to the query to allow the CTE to work fully.

Add a record for every Week-Day of the year to a blank table

I have a blank table that has two columns [ID] and [MyDate].
I would like to populate that table with all of the days of the current year MINUS weekends.
Is there a way to do this with a SQL query?
In this case I am using MSSQL T-SQL
I do not have any example code, as I am at a loss on where to get started for this scenario.
Using a numbers (Tally) table helps you to avoid using loops.
If you don't already have a numbers table, you can use this script to create it:
SELECT TOP 10000 IDENTITY(int,0,1) AS Number
INTO Tally
FROM sys.objects s1
CROSS JOIN sys.objects s2
ALTER TABLE Tally ADD CONSTRAINT PK_NumbersTest PRIMARY KEY CLUSTERED (Number)
For more information about the creation of a numbers table, read this SO post.
Now that you have a numbers table, you can use a cte to generate the dates you want. I've used DATEFROMPARTS and GETDATE() to get Jauary 1st of the current year, if you are using a version of sql server below 2012 you need to use other methods for that:
DECLARE #StartDate Date,
#EndDate Date
SELECT #StartDate = DATEFROMPARTS(YEAR(GetDate()), 1, 1)
SELECT #EndDate = DATEADD(Year, 1, #StartDate)
Now, create a CTE to get the dates required using the numbers table, and insert the records from the cte to the table:
;WITH CTE AS
(
SELECT DATEADD(Day, Number, #StartDate) As TheDate
FROM Tally
WHERE DATEADD(Day, Number, #StartDate) < #EndDate
)
INSERT INTO WeekDays
SELECT TheDate
FROM CTE
WHERE DATEPART(WeekDay, TheDate) BETWEEN 2 AND 6
See a live demo on rextester.
This will do it. Here the 1 and the 7 represents Sunday and Saturday
CREATE TABLE T (
ID INT NOT NULL IDENTITY(1,1),
MyDate DATE NOT NULL)
DECLARE #Start DATE
DECLARE #End DATE
SET #Start = '20170101'
SET #End = '20171231'
WHILE #Start <= #End
BEGIN
IF (DATEPART(DW, #Start) NOT IN (1,7))
BEGIN
INSERT INTO T (MyDate) VALUES (#Start)
END
SET #Start = DATEADD(DAY, 1, #Start)
END
SELECT * FROM T
Here's my quick attempt at your problem. Just use your table instead
select
CAST('2017-03-15' as datetime) as datestuff
into #test
Delete from #test
DECLARE #Y datetime = CAST('2017-12-31' AS DATE)
while #y != '2017-01-01'
begin
if DATENAME(DW, #y) not IN ('SUNDAY', 'SATURDAY')
BEGIN
INSERT INTO #test
SELECT #y
END
SET #Y = DATEADD(DD, -1, #Y)
end
select * from #test

Displaying the number of valid results for a range of dates

I currently have a table with a creation date and a expiry date. I currently have a sql command to get the number of valid items for a given date.
select
count(id) ,CONVERT(date, getdate())
from
table
where
createDate < getdate() and expDate > getdate()
This returns the count and current date.
Is it possible to wrote a sql query that will return the result for a range of dates, say I if wanted to plot the number of valid items over a range of 15 days?
Thanks!
Try this:
create table #datelist (ValidDateCheck date, ValidResults int)
declare #startdate date = '1/1/2015'
declare #enddate date = '2/1/2015'
declare #interval int = 1 --Use 1 if you want every day between your dates, use 2 if you want every other day, etc.
declare #datecounter date = #startdate
declare #count int
while #datecounter <= #enddate
begin
set #count =
(select count(*)
from Table
where CrtDt <= #datecounter and ExpDt > #datecounter)
insert into #datelist values (#datecounter, #count)
set #datecounter = dateadd(dd, #interval, #datecounter)
end
select * from #datelist order by 1
It loops through all the dates in your range, counting valid results for each one.
Check this,
DECLARE #StartDate DATETIME,
#EndDate DATETIME;
SELECT #StartDate = '20110501'
,#EndDate = '20110801';
SELECT
DATEADD(d, x.number, #StartDate) AS MonthName1
,
x.number
FROM master.dbo.spt_values x
WHERE x.type = 'P'
AND x.number <= DATEDIFF(MONTH, #StartDate, #EndDate);
The above query give the list of dates between 2 dates.
As per your table and question, check this also.
declare #table table(id int,frdt datetime, todt datetime)
insert into #table values (1,GETDATE()-20, GETDATE()-19)
,(2,GETDATE()-9, GETDATE()-8)
,(3,GETDATE()+20, GETDATE()+18)
,(4,GETDATE(), GETDATE()-1)
,(5,GETDATE()-20, GETDATE())
,(6,GETDATE()-10, GETDATE()+10 )
select * from #table
declare #frdt datetime = null , #todt datetime = getdate()-10
select #frdt, #todt,* from #table
where
(#frdt is null or #frdt between frdt and todt)
and
(#todt is null or #todt between frdt and todt)
select #frdt = GETDATE()-15 , #todt = GETDATE()
select #frdt, #todt,* from #table
where
(#frdt is null or #frdt between frdt and todt)
and
(#todt is null or #todt between frdt and todt)

SSIS job including SQL which creates temporary table

Have constructed a query which basically looks at a table which contains all bank holidays and then looks at each month for current financial year, then tells me how many working days are available to work minus the bank hols and weekends. For example this month there are 21. There is also a cumulative filed which basically adds up each month so the cumulative for April-Feb will have all those days added.
Within the query there is a CreateTable #DATA which is dropped at the end, this works fine within Management Studio and runs correctly.
My problem is that I am doing an SSIS job and have saved my query as a SQL file and have selected it using the 'Browse' button. It is not allowing me to continue as I believe it has a problem with the temporary table (See screenshot)
Any suggestions on how I can get this to work while maintaining functionality?
Please see code for reference:
DECLARE #StartDate DATETIME,
#EndDate DATETIME
SELECT #StartDate = (select
case when month(getdate()) >= 4 then
convert(datetime, cast(year(getdate()) as varchar) + '-4-1')
else
convert(datetime, cast(year(getdate())-1 as varchar) + '-4-1')
end),
#EndDate = (select
case when month(getdate()) < 4 then
convert(datetime, cast(year(getdate()) as varchar) + '-3-31')
else
convert(datetime, cast(year(getdate())+1 as varchar) + '-3-31')
end)
CREATE TABLE #data
(
firstday DATETIME NOT NULL PRIMARY KEY,
workingdays INT NOT NULL
);
WITH dayscte ([Date])
AS (SELECT #StartDate
UNION ALL
SELECT Dateadd(DAY, 1, [Date])
FROM dayscte
WHERE [Date] <= #Enddate)
INSERT INTO #data
SELECT MIN([Date]),
COUNT(*) [Day]
FROM table2
LEFT JOIN [dbo].[mydb].[mytable1]
ON [Date] BETWEEN [dbo].[mydb].[mytable1].startdate AND [dbo].[mydb].[mytable1].enddate
where
NOT EXISTS (
SELECT field1,field2 FROM [dbo].[mydb].[mytable1].tscheme_cal WHERE
dayid ='0234572347854234'
AND
[date] <= startdate
AND
[date] >= enddate
)
AND Datename(weekday, [Date]) NOT IN ( 'Saturday', 'Sunday' )
GROUP BY Datepart(MONTH, [Date]),
Datepart(YEAR, [Date])
OPTION (MAXRECURSION 366)
DECLARE #Date DATETIME
SET #Date = (SELECT MIN(firstday)
FROM #data)
SELECT Period,
workingdays [Days_Available] ,
year (firstday) AS [Year]
FROM (SELECT Datename(MONTH, firstday) [Period],
workingdays,
0 [SortField],
firstday
FROM #data
UNION
SELECT Datename(MONTH, #Date) + ' - ' + Datename(MONTH, firstday),
(SELECT SUM(workingdays)
FROM #data b
WHERE b.firstday <= a.firstday) [WorkingDays],
1 [SortField],
firstday
FROM #data a
WHERE
firstday > #Date) data
ORDER BY sortfield,
firstday
DROP TABLE #data
its not easy dealing with temp tables on SSIS.
I suggest this article:
http://www.sqllike.com/using-temporary-tables-with-ssis.html
it is a solution, but I don't like it.
I sometimes i use table variables or create a regular table on the DB and then drop it in the end.
In SSIS I find that table variables work well. You can't use temp tables even in a stored proc if it is the source code for a transformation.
In SQL Server 2012 if you use temporary tables you must specify a results set.
This is an issue with the sp_describe_first_result_set procedure that SSIS uses to returns the output metadata.
E.g.
EXEC dbo.RptResults_StoredProcedure
Becomes
EXEC dbo.RptResults_StoredProcedure
WITH RESULT SETS
((
Date NVARCHAR(10),
Location VARCHAR(12),
Department CHAR(1),
Shift CHAR(1),
ForecastSales DECIMAL(18,2),
ActualSales DECIMAL(18,2)
))
For more information view
http://blog.concentra.co.uk/2014/08/22/column-metadata-determined-correctly-ssis-data-flow-task-stored-procedure-inputs/
http://blog.concentra.co.uk/2014/08/22/column-metadata-determined-correctly-ssis-data-flow-task-stored-procedure-inputs/