I have a row being inserted into [Server1].[DatabaseA].[dbo].[EMRVisit]. I need to add some information to the Visit record from linked server [Server2].[DatabaseB], so I set up an AFTER INSERT trigger.
Both servers are MSSQL 2016, databases are running at 2008 compatibility at the moment.
Currently, the trigger is blocking insertion of the row. I'm not seeing anything in Profiler, other that the Insert attempt and a rollback. Also, it's not generating any other errors. The code runs fine outside the trigger.
The frustrating part of this, is that the trigger was operating fine as is on older 2008 boxes.
ALTER TRIGGER [dbo].[Pt_Note_Edit]
ON [dbo].[EMRVisit]
AFTER INSERT
AS
IF ((SELECT TRIGGER_NESTLEVEL()) < 2)
BEGIN
DECLARE #med_rec_nbr varchar(15), #Days VARCHAR(20), #OldNote nvarchar(MAX), #NewNote nvarchar(MAX)
SET #med_rec_nbr = (SELECT ept.PatientChartNumber FROM INSERTED ev INNER JOIN [Server1].[DatabaseA].[dbo].[Patients] ept ON ev.PtID = ept.PtID)
--Collect ADS Data
--Convert #med_rec_nbr to #Account
DECLARE #Account varchar(15)
EXEC [Server2].[DatabaseB].[dbo].ADS_CleanUp_MRN #med_rec_nbr, #Account=#Account OUTPUT
SELECT *
INTO #PtChgs
FROM [Server2].[DatabaseB].[dbo].ADS_Charges
WHERE AccountNo = #Account
--Get Old Pt Note
SELECT #OldNote = ept.PatientNote
FROM [Server1].[DatabaseA].[dbo].[Patients] ept
WHERE ept.PatientChartNumber = #med_rec_nbr
--Edit OldNote
DECLARE #NotePart nvarchar(MAX), #Trans Int
SET #NotePart = CASE
WHEN #OldNote IS NOT NULL THEN SUBSTRING(#OldNote,CHARINDEX('~',#OldNote,1)+1,LEN(#OldNote))
ELSE ''
END
--Get Latest Post Op Charges
SELECT Charges.FromDate
,Charges.Modifiers
,DATEDIFF(DAY, Charges.FromDate, GETDATE()) AS DaysIn
INTO #PtPostOp
FROM [Server2].[DatabaseB].[dbo].[Charges] Charges
JOIN [Server2].[DatabaseB].[dbo].[ProcedureCodes] PC ON Charges.Cpt = PC.Code
WHERE Charges.AccountNo = #Account
AND Charges.FromDate > CONVERT(VARCHAR, DATEADD (DAY , -(PC.NumberOfDays + 10) , GETDATE()), 112)
AND PC.NumberOfDays <> 0
ORDER BY Charges.FromDate DESC
DECLARE #FromDate integer,#Modifiers VARCHAR(5), #DaysIn VARCHAR (2), #Enc_Rows int, #Mod varchar(3)
--Get count of encounters in Post Op period for current patient
SET #Enc_Rows = 0
SELECT #Enc_Rows = COUNT(*) FROM #PtPostOp
--Loop through records and concatenate rows
SET #Days = ''
WHILE #Enc_Rows > 0
BEGIN
--Get first record
SELECT TOP 1 #FromDate = FromDate
,#Modifiers = CASE
WHEN Modifiers LIKE '%RT%' THEN 'OD'
WHEN Modifiers LIKE '%LT%' THEN 'OS'
ELSE Modifiers
END
,#DaysIn = DaysIn
FROM #PtPostOp
ORDER BY FromDate DESC
--Concatenate Row
SET #Days = #Days + #Modifiers + ' ' + #DaysIn + ' days'
IF #Enc_Rows > 1
SET #Days = #Days + ': '
SET #Enc_Rows = #Enc_Rows -1
DELETE FROM #PtPostOp WHERE FromDate = #FromDate
END
IF #Days <> ''
SET #NewNote = ('**POST OP ' + #Days + ' ** ~' + #NotePart)
ELSE
SET #NewNote = #NotePart
--Update the PatientNote
UPDATE [Server1].[Database].[dbo].[Patients]
SET PatientNote = #NewNote
WHERE PatientChartNumber = #med_rec_nbr
END
As an addition to this - I'm also attempting to add a try - catch to my code, but that is generating DTC errors.
Related
With the below function I getting the result as 00:09:10 however I want the result to be as 01:00:10.
So hours is considered as considered as 1 day.
Example if hours is 30 then it will be 03:03:00 and so on
fn_GetHolidayMinutes : Get holiday in minutes between two dates and country
CREATE FUNCTION [dbo].[fn_GetHolidayMinutes]
(#StartDate DATETIME,
#EndDate DATETIME,
#CountryId BIGINT)
RETURNS BIGINT
AS
BEGIN
DECLARE #OUTPUT BIGINT;
DECLARE #HolidayList TABLE (HolidaysDate DATE)
-- Create Table #HolidayList
-- (
-- HolidaysDate date
-- )
DECLARE #Date1 DATE, #Date2 DATE
DECLARE holiday_cursor CURSOR FOR
SELECT StartDate,EndDate
FROM Holidays
WHERE IsActive = 1
AND CountryId = #CountryId
AND ((StartDate BETWEEN #StartDate AND #EndDate) OR
(EndDate BETWEEN #StartDate AND #EndDate))
OPEN HOLIDAY_CURSOR
FETCH NEXT FROM HOLIDAY_CURSOR INTO #Date1, #Date2
WHILE ##FETCH_STATUS = 0
BEGIN
--INSERT INTO #HolidayList
INSERT INTO #HolidayList
SELECT DATEADD(DAY, number, #Date1) [Date]
FROM master..spt_values
WHERE type = 'P'
AND DATEADD(DAY, number, #Date1) <= #Date2
FETCH NEXT FROM HOLIDAY_CURSOR INTO #Date1, #Date2
END
CLOSE HOLIDAY_CURSOR;
DEALLOCATE HOLIDAY_CURSOR;
(SELECT #OUTPUT= COUNT(DISTINCT HolidaysDate)
FROM #HolidayList
WHERE HolidaysDate BETWEEN #StartDate AND #EndDate
AND DATEPART(dw, HolidaysDate) NOT IN (SELECT DISTINCT number
FROM master..spt_values
WHERE number BETWEEN 1 and 7
AND number NOT IN (SELECT WorkingDay
FROM WorkingDays
WHERE CountryId = #CountryId AND IsActive = 1)
))
---print #OUTPUT; --this will give in days
--get the output in minutes
RETURN #OUTPUT * (SELECT TOP 1 STUFF(WorkingHours, 2, 2, '')
FROM dbo.WorkingDays
WHERE CountryId = #CountryId) * 60;
END
fn_GetWorkingDayMinuts :
CREATE FUNCTION [dbo].[fn_GetWorkingDayMinuts]
(#StartDate DATETIME,
#EndDate DATETIME,
#CountryId BIGINT)
--RETURNS BIGINT
RETURNS VARCHAR(250)
AS
BEGIN
DECLARE #Temp BIGINT
SET #Temp = 0
DECLARE #FirstDay DATE
SET #FirstDay = CONVERT(DATE, #StartDate, 112)
DECLARE #LastDay DATE
SET #LastDay = CONVERT(DATE, #EndDate, 112)
DECLARE #StartTime TIME
SET #StartTime = CONVERT(TIME, #StartDate)
DECLARE #FinishTime TIME
SET #FinishTime = CONVERT(TIME, #EndDate)
DECLARE #WorkStart TIME
SET #WorkStart = (SELECT CONVERT(VARCHAR(5),CONVERT(TIME, CONVERT(VARCHAR,CONVERT(DATE, GETDATE()))+ ' ' + (SELECT TOP 1
WorkStartTime FROM WorkingDays WHERE CountryId=#CountryId), 120)))
DECLARE #WorkFinish TIME
SET #WorkFinish = (SELECT CONVERT(VARCHAR(5),CONVERT(TIME, CONVERT(VARCHAR,CONVERT(DATE, GETDATE()))+ ' ' + (SELECT TOP 1
WorkEndTime FROM WorkingDays WHERE CountryId=#CountryId), 120)))
DECLARE #DailyWorkTime BIGINT
SET #DailyWorkTime = DATEDIFF(MINUTE, #WorkStart, #WorkFinish)
IF (#StartTime<#WorkStart)
BEGIN
SET #StartTime = #WorkStart
END
IF (#FinishTime>#WorkFinish)
BEGIN
SET #FinishTime=#WorkFinish
END
IF (#FinishTime<#WorkStart)
BEGIN
SET #FinishTime=#WorkStart
END
IF (#StartTime>#WorkFinish)
BEGIN
SET #StartTime = #WorkFinish
END
DECLARE #CurrentDate DATE
SET #CurrentDate = #FirstDay
DECLARE #LastDate DATE
SET #LastDate = #LastDay
WHILE(#CurrentDate<=#LastDate)
BEGIN
--IF (DATEPART(dw, #CurrentDate)!=1 AND DATEPART(dw, #CurrentDate)!=7)
IF(DATEPART(dw, #CurrentDate) IN (SELECT distinct number FROM master..spt_values WHERE number BETWEEN 1 and 7
AND number NOT IN (SELECT
WorkingDay FROM WorkingDays where CountryId=#CountryId and IsActive=1)
))
BEGIN
IF (#CurrentDate!=#FirstDay) AND (#CurrentDate!=#LastDay)
BEGIN
SET #Temp = #Temp + #DailyWorkTime
END
--IF it starts at startdate and it finishes not this date find diff between work finish and start as minutes
ELSE IF (#CurrentDate=#FirstDay) AND (#CurrentDate!=#LastDay)
BEGIN
SET #Temp = #Temp + DATEDIFF(MINUTE, #StartTime, #WorkFinish)
END
ELSE IF (#CurrentDate!=#FirstDay) AND (#CurrentDate=#LastDay)
BEGIN
SET #Temp = #Temp + DATEDIFF(MINUTE, #WorkStart, #FinishTime)
END
--IF it starts and finishes in the same date
ELSE IF (#CurrentDate=#FirstDay) AND (#CurrentDate=#LastDay)
BEGIN
SET #Temp = DATEDIFF(MINUTE, #StartTime, #FinishTime)
END
END
SET #CurrentDate = DATEADD(day, 1, #CurrentDate)
END
-- Return the result of the function
IF #Temp<0
BEGIN
SET #Temp=0
END
--RETURN #Temp -(dbo.fn_GetHolidayMinutes (DATEADD(dd, 0, DATEDIFF(dd, 0, #StartDate)),DATEADD(dd, 0, DATEDIFF(dd, 0,
#EndDate)),#CountryId))
--RETURN #Temp
DECLARE #theMinutes INT
DECLARE #Result VARCHAR(250)
SET #theMinutes = #Temp -(dbo.fn_GetHolidayMinutes (DATEADD(dd, 0,
DATEDIFF(dd, 0, #StartDate)),DATEADD(dd, 0, DATEDIFF(dd, 0,
#EndDate)),#CountryId))
--SET #Result= concat((#theMinutes / 540),':' , (#theMinutes % 540) /
60, ':', (#theMinutes % 60))
SET #Result= concat((#theMinutes / ((SELECT TOP 1
STUFF(WorkingHours,2,2,'') FROM dbo.WorkingDays WHERE
CountryId=#CountryId) * 60)),':' , (#theMinutes % ((SELECT TOP 1
STUFF(WorkingHours,2,2,'') FROM dbo.WorkingDays WHERE
CountryId=#CountryId) * 60)) / 60, ':', (#theMinutes % 60))
RETURN #Result
END
So where to modify to the result as
BUSINESS HOURS CREATE DATE & TIME FIRST APPLY (DATE & TIME) TAT TIME CALCULATION RESULT
08h00-17h00: 9hrs/day 12-FEB-19 14:20 13-FEB-19 14:30 00:02:40 + 00:06:30 = 00:09:10 01:00:10
I have the below supplier data in SSRS 2008 report.
ID Name Details Email
1 abc d1 rob.b#gmail.com
2 def d2 pat#gmail.com
3 ghi d3 golf#gmail.com
4 dft d4 rob.b#gmail.com
I need to send the relevant details to each email id. For example, in the data above, I need to send the entire record of ID 1 and 4 to rob.b#gmail.com.
Is there any way to send just the relevant details to the emails given in the report. Could someone please advise.
Yes - you can use a Data Driven Subscription to do this in SSRS - if you have the Enterprise version of SQL Server.
If you do not have the Enterprise version, you can still do this with a little bit more effort using a scheduled Stored Procedure to emulate the data driven subscription.
Either way, you would have a report that works with a parameter to identify a single record. Then the separate data driven part would have a different query that gets a list of IDs that you need for the report along with the e-mail address to send it to. The data driven part will then generate a separate report for each of the ID parameter that you created in the report and then send them to the address.
Data Driven Subscription properties:
Unfortunately, both methods are too big of a topic to be covered in an answer.
MSDN - Data Driven Subscriptions
MSSQLTips.com - simulate-reporting-services-data-driven-subscriptions
Here's a SP that I made to generate multiple e-mail:
ALTER PROCEDURE [dbo].[RECORD_REVIEW_GENERATION]
AS
DECLARE #SUBSCRIPTION_ID AS VARCHAR(100) = (SELECT SETTING_VALUE FROM WORKING_STORAGE.dbo.SETTINGS WHERE SETTING_NAME = 'REVIEW_SUBSCRIPTION')
DECLARE #SUBJECT VARCHAR(200)
DECLARE #COMMENT VARCHAR(500)
DECLARE #REVIEW_ID VARCHAR(50)
DECLARE #EXTENSION_SETTINGS XML
DECLARE #PARAMETERS XML
DECLARE #RECORD_ID AS INT
DECLARE #MAX_RECORD_ID AS INT
DECLARE #END_DATE AS DATE = GETDATE() - DATEPART(WEEKDAY, GETDATE()) --PREVIOUS SUNDAY
DECLARE #START_DATE AS DATE = DATEADD(DAY, -6, #END_DATE) --PREVIOUS MONDAY
DECLARE #DATE VARCHAR(500) = CONVERT(VARCHAR(8), #END_DATE, 112)
SELECT #EXTENSION_SETTINGS = ExtensionSettings, #PARAMETERS = [Parameters]
FROM ReportServer.dbo.Subscriptions
WHERE SubscriptionID = #SUBSCRIPTION_ID;
IF OBJECT_ID('tempdb..#REVIEWS') IS NOT NULL DROP TABLE #REVIEWS
CREATE TABLE #REVIEWS(ReviewID VARCHAR(50), ProviderName VARCHAR(250), SiteIDNo VARCHAR(20),
ReviewDate VARCHAR(12), UserName VARCHAR(250), VisitPurpose VARCHAR(250),
NoOfPhysicians INT, NoOfRecords INT, RECORD_ID INT IDENTITY(1,1)
)
INSERT INTO #REVIEWS(ReviewID, ProviderName, SiteIDNo, ReviewDate, UserName, VisitPurpose, NoOfPhysicians, NoOfRecords)
SELECT ReviewID, ProviderName, SiteIDNo, ReviewDate, UserFirstName + ' ' + UserLastName AS UserName, VisitPurpose, NoOfPhysicians, NoOfRecords
FROM KHSSQLODSPRD.QI_SITE_REVIEW.dbo.RecordHeader
WHERE ExportDate BETWEEN #START_DATE AND #END_DATE
ORDER BY ReviewDate
SET #RECORD_ID = 1
SET #MAX_RECORD_ID = (SELECT ISNULL(MAX(RECORD_ID), 0) FROM #REVIEWS)
WHILE #RECORD_ID <= #MAX_RECORD_ID
BEGIN
SELECT #REVIEW_ID = ReviewID,
#SUBJECT = 'Review - ' + ProviderName,
#COMMENT = CAST(#RECORD_ID AS VARCHAR(10)) + ' of ' + CAST(#MAX_RECORD_ID AS VARCHAR(10))
+ ' Review Surveys for the week ending ' + RTRIM(CONVERT(VARCHAR(12), #END_DATE, 110)) + '.'
+ CHAR(13) + CHAR(10) + CHAR(13) + CHAR(10) + ProviderName + ' [' + SiteIDNo + '] - Reviewed ' + RTRIM(CONVERT(VARCHAR(12), ReviewDate, 110))
+ '. Review ID ' + ReviewID
+ CHAR(13) + CHAR(10) + CHAR(13) + CHAR(10) + VisitPurpose + ' visit for ' + CAST(CAST(NoOfPhysicians AS INT) AS VARCHAR(20)) + ' physicians with '
+ CAST(CAST(NoOfRecords AS INT) AS VARCHAR(20)) + ' records by ' + UserName + '.'
FROM #REVIEWS
WHERE RECORD_ID = #RECORD_ID
SET #REVIEW_ID = LOWER(#REVIEW_ID)
--SET EXTENSION OPTIONS
SET #EXTENSION_SETTINGS.modify('replace value of (/ParameterValues/ParameterValue[Name="Subject"]/Value/text())[1] with sql:variable("#SUBJECT")');
SET #EXTENSION_SETTINGS.modify('replace value of (/ParameterValues/ParameterValue[Name="Comment"]/Value/text())[1] with sql:variable("#COMMENT")');
--SET REPORT PARAMETERS
SET #PARAMETERS.modify('replace value of (/ParameterValues/ParameterValue[Name="SITE_ID"]/Value/text())[1] with sql:variable("#REVIEW_ID")');
--UPDATE SUBSCRIPTION PARAMETERS
UPDATE dbo.Subscriptions
SET ExtensionSettings = CAST(#EXTENSION_SETTINGS AS VARCHAR(8000)),
[Parameters] = CAST(#PARAMETERS AS VARCHAR(8000))
WHERE SubscriptionID = #SUBSCRIPTION_ID
EXEC dbo.AddEvent #EventType = 'TimedSubscription', #EventData = #SUBSCRIPTION_ID;
--WAIT WHILE REPORT GENERATES
WAITFOR DELAY '00:00:03.000';
--IF REPORT IS STILL EXECUTING, WAIT SOME MORE
WHILE EXISTS (SELECT TOP 1 'X' FROM dbo.Event WHERE EventData = #SUBSCRIPTION_ID ) OR EXISTS (SELECT TOP 1 'X' FROM dbo.Notifications WHERE SubscriptionID = #SUBSCRIPTION_ID)
BEGIN
WAITFOR DELAY '00:00:01.000';
PRINT 'Waiting for subscription to finish'
END
SET #RECORD_ID = #RECORD_ID + 1
END --END OF LOOP
-- SET #FLAG = 1
You'd add the TO address the same way as the Comment is updated. The #Review_ID is passed to the report as a parameter.
Using SQL Server 2012. I need to loop through my table without using a cursor or a temp table. Also, I know the debate re: cursors... :) AND I have script at the bottom of this question using sys.databases and msdb.dbo.restorehistory getting the last restored, but this doesn't fix my immediate need for this specific table.
Scenario: I have a table that I created for restore tests:
CREATE Table RestoreTests (
RestoreTestID int Not NULL,
ServerName varchar (255) Not NULL,
DatabaseName varchar (255) Not NULL,
RestoreDate datetime Not NULL,
BackupFile varchar (1000) Not NULL)
I inserted 8 records with:
2 servers - 4 records/server,
.bak and .trn for each DatabaseName, and
dates < 30 days and dates > 30 days - 4 records each.
I want to identify all records on my table that are > 30 days.
SELECT * FROM RestoreTests WHERE RestoreDate DATEDIFF(Day,RestoreDate, GETDATE()) > 30
My syntax:
declare #RestoreTestID int
declare #ServerName varchar(255)
declare #DatabaseName varchar(255)
declare #RestoreDate datetime
declare #BackupFile varchar(1000)
declare #id int
set #id = 0
select top 1 #RestoreTestID = RestoreTestID,
#ServerName = ServerName,
#DatabaseName = DatabaseName,
#RestoreDate = RestoreDate,
#BackupFile = BackupFile
from dbo.RestoreTests
where RestoreTestID > #id and DATEDIFF(DAY,RestoreDate, GETDATE()) > 30
order by RestoreTestID asc
while ##ROWCOUNT > 0
begin
print 'loop RestoreTestID=' + cast(#RestoreTestID as varchar(255)) +
', ServerName=' + #ServerName +
', DatabaseName' + #DatabaseName +
', RestoreDate' + CAST(#RestoreDate as varchar(255)) +
', BackupFile' + #BackupFile
set #id = #RestoreTestID
select top 1 #RestoreTestID = RestoreTestID
from dbo.RestoreTests
where RestoreTestID > #id and DATEDIFF(DAY,RestoreDate, GETDATE()) > 30
order by RestoreTestID
end
I'm getting error message:
Msg 137, Level 15, State 1, Line 1
Must declare the scalar variable "#RestoreTestID".
Msg 137, Level 15, State 2, Line 13
Must declare the scalar variable "#RestoreTestID".
Msg 137, Level 15, State 2, Line 19
Must declare the scalar variable "#RestoreTestID".
Msg 137, Level 15, State 1, Line 21
Must declare the scalar variable "#RestoreTestID".
When I was dinking around earlier I did get a result set with all eight records and not the 4 that are over 30 days. Any assistance offered is greatly appreciated!!
Last Restore Syntax:
WITH LastRestores AS
(
SELECT
DatabaseName = [d].[name] ,
[d].[create_date] ,
[d].[compatibility_level] ,
[d].[collation_name] ,
r.*,
RowNum = ROW_NUMBER() OVER (PARTITION BY d.Name ORDER BY r.[restore_date] DESC)
FROM master.sys.databases d
LEFT OUTER JOIN msdb.dbo.[restorehistory] r ON r.[destination_database_name] = d.Name
)
SELECT *
FROM [LastRestores]
WHERE [RowNum] = 1
select * from [dbo].[RestoreTests]
Ok, I figured out what I needed. Here's the syntax I arrived at:
declare #RestoreTestID int
declare #id int
declare #ServerName varchar(255);
declare #DatabaseName varchar (255);
declare #RestoreDate datetime;
declare #BackupFile varchar (1000);
set #id = 0
select top 1
#RestoreTestID = RestoreTestID,
#ServerName = ServerName,
#DatabaseName = DatabaseName,
#RestoreDate = RestoreDate,
#BackupFile = BackupFile
from dbo.RestoreTests
where RestoreTestID > #id and RestoreDate <= DATEADD(day,-31,getdate())
order by RestoreTestID
while ##ROWCOUNT = 1
begin
print 'RestoreTestID = ' + cast(#RestoreTestID as varchar(255)) +
', ServerName = ' + #ServerName +
', Databasename = ' + #DatabaseName +
', RestoreDate = ' + cast(#RestoreDate as varchar (255)) +
', BackupFile = ' + #BackupFile
set #id = #RestoreTestID
select top 1 #RestoreTestID = RestoreTestID
from dbo.RestoreTests
where RestoreTestID > #id and RestoreDate <= DATEADD(day,-31,getdate())
order by RestoreTestID
end
I want to reduce the time it takes for one of my stored procs that currently uses the following logic to calculate the date field, both in Select and Group portion:
left(datename(month, a.QXP_REPORT_DATE), 3) + ' ''' + right(datename(year, a.QXP_REPORT_DATE), 2)
Would a simple lookup table take less time? If so, then how would I populate for the following fields for all dates in the last 2 years?
CREATE TABLE #CALENDAR(
FULLDATE DATETIME,
MONTHNAME NVARCHAR(3),
sYEAR SMALLINT
)
INSERT INTO #CALENDAR
SELECT '4/19/2011', left(datename(month, '4/19/2011'), 3), right(datename(year, '4/19/2011'), 2)
I'm starting to think maybe a function call would be better than a lookup table. Here is all of my SQL stored proc:
DECLARE
#FirstMonthDate DATETIME,
#LastMonthDate DATETIME,
#TheLevel INT,
#ProductGroup VARCHAR(255),
#TheCategory VARCHAR(255),
#ListNumber VARCHAR(50)
--AS
-- SET NOCOUNT ON;
--ComplaintTrendingDrillDown3p '3/1/10', '3/31/11 23:59:59', 3 , 'RealTime IVD', 'Procedure Not Followed', ''
SET #FirstMonthDate = '3/1/11'
SET #LastMonthDate = '3/31/11 23:59:59'
SET #TheLevel = 3
SET #ProductGroup = 'RealTime IVD'
SET #TheCategory = 'Procedure Not followed'
--SET #ListNumber = '2G31-90'
DECLARE #SelectedLevels table (LevelId int not null primary key)
declare #OneYearAgo datetime
set #OneYearAgo = dateadd(year, -1, #FirstMonthDate)
IF #TheLevel = 3
BEGIN
INSERT INTO #SelectedLevels (LevelId) VALUES (1)
INSERT INTO #SelectedLevels (LevelId) VALUES (2)
END
ELSE if #TheLevel = 5
BEGIN
INSERT INTO #SelectedLevels (LevelId) VALUES (0)
INSERT INTO #SelectedLevels (LevelId) VALUES (1)
INSERT INTO #SelectedLevels (LevelId) VALUES (2)
END
ELSE
BEGIN
INSERT INTO #SelectedLevels (LevelId) VALUES (#TheLevel)
END
SELECT count(distinct a.QXP_EXCEPTION_NO) AS QXP_EXCEPTION_NO, PRODUCT_CODE_STD, a.qxp_short_desc,
left(datename(month, a.QXP_REPORT_DATE), 3) + ' ''' +
right(datename(year, a.QXP_REPORT_DATE), 2) AS MonthYear ,
CASE WHEN a.QXP_SHORT_DESC = #TheCategory OR ISNULL(#TheCategory, '') = '' THEN 1 ELSE 0 END AS SELECTED_CATEGORY
FROM ALL_COMPLAINTS a
INNER JOIN #SelectedLevels F ON A.[LEVEL] = F.LevelId
LEFT OUTER JOIN MANUAL.PRODUCTS b ON a.EPA_PRD_CODE = b.LIST_NUMBER
LEFT OUTER JOIN SMARTSOLVE.V_CXP_CUSTOMER_PXP c ON a.QXP_ID = c.QXP_ID
WHERE a.QXP_REPORT_DATE >= #OneYearAgo AND
a.QXP_REPORT_DATE <= #LastMonthDate AND a.QXP_SHORT_DESC <> 'Design Control'
AND (c.QXP_EXCEPTION_TYPE <> 'Non-Diagnostic' OR c.QXP_EXCEPTION_TYPE IS NULL)
AND PRODUCT_GROUP= #ProductGroup
AND (PRODUCT_CODE_STD = #ListNumber OR ISNULL(#ListNumber, '') = '')
and left(datename(month, a.QXP_REPORT_DATE), 3) = 'may'
GROUP BY PRODUCT_CODE_STD, left(datename(month, a.QXP_REPORT_DATE), 3) + ' ''' + right(datename(year, a.QXP_REPORT_DATE), 2) , a.qxp_short_desc
order by left(datename(month, a.QXP_REPORT_DATE), 3) + ' ''' +
right(datename(year, a.QXP_REPORT_DATE), 2), product_code_std, qxp_short_desc
Execution plan recommendations:
CREATE NONCLUSTERED INDEX [<Name of Missing Index, sysname,>]
ON [SMARTSOLVE].[V_CXP_CUSTOMER_PXP] ([QXP_REPORT_DATE],[QXP_UDF_STRING_8],[QXP_XRS_DESCRIPTION])
INCLUDE ([QXP_ID],[QXP_EXCEPTION_NO],[QXP_BASE_EXCEPTION],[QXP_OCCURENCE_DATE],[QXP_COORD_ID],[QXP_ROOT_CAUSE],[QXP_DESCRIPTION],[QXP_QEI_ID],[QXP_EXCEPTION_TYPE],[QXP_UDF_STRING_2],[QXP_UDF_STRING_5],[CXP_ID],[CXP_AWARE_DATE],[QXP_XSV_CODE],[QXP_COORD_NAME],[QXP_ORU_NAME],[QXP_RESOLUTION_DESC],[QXP_CLOSED_DATE],[CXP_CLIENT_CODE],[CXP_CLIENT_NAME])
I have this statement in T-SQL.
SELECT Bay From TABLE where uid in (
select B_Numbers from Info_Step WHERE uid = 'number'
)
I am selecting "multiple" BAYs from TABLE where their uid is equal to a string of numbers like this:
B_Numbers = 1:45:34:98
Therefore, I should be selecting 4 different BAYs from TABLE. I basically need to split the string 1:45:34:98 up into 4 different numbers.
I'm thinking that Split() would work, but it doesn't and I get a syntax error.
Any thoughts from the T-SQL gods would be awesome!
Here is an implementation of a split function that returns the list of numbers as a table:
http://rbgupta.blogspot.com/2007/03/split-function-tsql.html
Looks like this would set you on your way...
Here is a method that uses an auxiliary numbers table to parse the input string. The logic can easily be added to a function that returns a table. That table can then be joined to lookup the correct rows.
Step 1: Create the Numbers table
SET NOCOUNT ON
GO
IF EXISTS
(
SELECT 1
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = 'Numbers'
AND TABLE_SCHEMA = 'dbo'
AND TABLE_TYPE = 'BASE TABLE'
)
BEGIN
DROP TABLE dbo.Numbers
END
GO
CREATE TABLE dbo.Numbers
(
Number smallint IDENTITY(1, 1) PRIMARY KEY
)
GO
WHILE 1 = 1
BEGIN
INSERT INTO dbo.Numbers DEFAULT VALUES
IF SCOPE_IDENTITY() = 32767
BEGIN
BREAK
END
END
GO
Step 2: Parse the Input String
CREATE FUNCTION dbo.ParseString(#input_string varchar(8000), #delim varchar(8000) = " ")
RETURNS TABLE
AS RETURN
(
SELECT Number
FROM dbo.Numbers
WHERE CHARINDEX
(
#delim + CONVERT(VARCHAR(12),Number) + #delim,
#delim + #input_string + #delim
) > 0
)
GO
**EXAMPLE**
SELECT * FROM dbo.ParseString('1:45:34:98',':')
Step 3: Use the results however you want/need
Number
------
1
34
45
98
End-To-End Example
Create function that returns the appropriate BNumber (of course change it to use the commented out SQL)
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE FUNCTION dbo.GetBNumber (#uid int)
RETURNS VARCHAR(8000)
AS
BEGIN
RETURN '1:45:34:98'
--select B_Numbers from Info_Step WHERE uid = #uid
END
GO
Use the use functions to return the desired results
-- Using Test Data
SELECT N.Number FROM Numbers N
JOIN dbo.ParseString(dbo.GetBNumber(12345),':') Q ON Q.Number = N.Number
-- Using Your Data (Untested but should work.)
SELECT N.Bay
FROM TABLE N
JOIN dbo.ParseString(dbo.GetBNumber(ENTER YOU NUMBER HERE),':') Q ON Q.Number = N.uid
Results
Number
------
1
34
45
98
You should keep your arrays as rows but if I understand your question I think this will work.
SELECT
Bay
From
TABLE
join Info_Step
on B_Numbers like '%'+ uid +'%'
where
Info_Step.uid = 'number'
This query will do a full table scan because of the like operator.
What you can do is loop through the B_Numbers entries and do your own split on : Insert those entries into a temp table and then perform your query.
DECLARE #i int
DECLARE #start int
DECLARE #B_Numbers nvarchar(20)
DECLARE #temp table (
number nvarchar(10)
)
-- SELECT B_Numbers FROM Info_Step WHERE uid = 'number'
SELECT #B_Numbers = '1:45:34:98'
SET #i = 0
SET #start = 0
-- Parse out characters delimited by ":";
-- Would make a nice user defined function.
WHILE #i < len(#B_Numbers)
BEGIN
IF substring(#B_Numbers, #i, 1) = ':'
BEGIN
INSERT INTO #temp
VALUES (substring(#B_Numbers, #start, #i - #start))
SET #start = #i + 1
END
SET #i = #i + 1
END
-- Insert last item
INSERT INTO #temp
VALUES (substring(#B_Numbers, #start, #i - #start + 1))
-- Do query with parsed values
SELECT Bay FROM TABLE WHERE uid in (SELECT * FROM #temp)
You can even try this
declare #str varchar(50)
set #str = '1:45:34:98'
;with numcte as(
select 1 as rn union all select rn+1 from numcte where rn<LEN(#str)),
getchars as(select
ROW_NUMBER() over(order by rn) slno,
rn,chars from numcte
cross apply(select SUBSTRING(#str,rn,1) chars)X where chars = ':')
select top 1
Bay1 = SUBSTRING(#str,0,(select rn from getchars where slno = 1))
,Bay2 = SUBSTRING(#str,
(select rn from getchars where slno = 1) + 1,
(((select rn from getchars where slno = 2)-
(select rn from getchars where slno = 1)
)-1))
,Bay3 = SUBSTRING(#str,
(select rn from getchars where slno = 2) + 1,
(((select rn from getchars where slno = 3)-
(select rn from getchars where slno = 2)
)-1))
,Bay4 = SUBSTRING(#str,
(select rn from getchars where slno = 3)+1,
LEN(#str))
from getchars
Output:
Bay1 Bay2 Bay3 Bay4
1 45 34 98