SQL syntax issue using "IN" keyword with dynamic data - sql

I am using SQL Server 2000 and having a wierd issue with a SQL code block (below):
A user can enter "GM" as a possible parameter or "F". If the user enters "GM" as a parameter in the stored proc query string, I need the AutoDivision to include GMC, CAD, CHE,SAT
declare #AutoDivision as varchar(15)
set #AutoDivision = 'GM'
if #AutoDivision = 'GM'
Begin
Select #AutoDivision = '''Cad'', ''GMC'', ''Sat'', ''Che'''
End
SELECT
oh.OrderNumber, lg.[lgh_number]
FROM
[dbo].[OrderHeader] oh (NOLOCK)
INNER JOIN
[dbo].[DistrctHeader] lg (NOLOCK) ON oh.[inv_number] = lg.[inv_number]
INNER JOIN
[dbo].[DealerCompany] c (NOLOCK) ON c.cmp_id = LEFT(oh.[ordernumber],3)
INNER JOIN
[dbo].[divisionXREF] x (NOLOCK) ON x.Division = c.comp_revtype
WHERE
oh.ord_number = '113-889257'
AND x.AutoDivision IN (#AutoDivision)
--AND x.AutoDivision IN ('Cad', 'Sat', 'GMC', 'Che')
AND lg.[lgh_outstatus] IN ('AVAIL', 'PLAN', 'DISP', 'STRTD', 'PEND','COMP')
However, when I run the code below, I don't get back any records.
When I uncomment the code line
--AND x.AutoDivision IN ('Cad', 'Sat', 'GMC', 'Che')
it works (I get a record returned).
When I do a print 'AND x.AutoDivision IN (' + cast(#AutoDivision as varchar) + ')'
I get back AND x.AutoDivision IN ('Cad', 'GMC', 'Sat', 'Che')
What am I missing here?

You can't use a single variable to represent a comma separated list of IN parameters in SQL - Oracle, MySQL, SQL Server... doesn't matter.
To get this variable method to work, you need to use dynamic SQL so you are able to create the query as a string first (using concatenation to get the IN parameters from your variable), and the query statement is executed afterwards:
DECLARE #cmd VARCHAR(1000)
SET #cmd = 'SELECT oh.OrderNumber,
lg.[lgh_number]
FROM [dbo].[OrderHeader] oh (NOLOCK)
JOIN [dbo].[DistrctHeader] lg (NOLOCK) ON oh.[inv_number] = lg.[inv_number]
JOIN [dbo].[DealerCompany] c (NOLOCK) ON c.cmp_id = LEFT(oh.[ordernumber],3)
JOIN [dbo].[divisionXREF] x (NOLOCK) ON x.Division = c.comp_revtype
WHERE oh.ord_number = '113-889257'
AND x.AutoDivision IN ('+ #AutoDivision +')
AND lg.[lgh_outstatus] IN (''AVL'', ''PLN'', ''DSP'', ''STD'', ''PND'',''CMP'') '
EXEC(#cmd)
I recommend reading The Curse and Blessings of Dynamic SQL before implementing a dynamic SQL solution.
Table Valued Function
A table valued function would allow you do what you want without using dynamic SQL -- there's more info in this article.

To avoid this, you can create a temp table, fill it in, then use
IN (SELECT myField from #myTable)

Even though you concatenate what looks like a few different arguments your IN clause is actually testing it as a single string (you did declare it as a varchar) and it's no surprise that no records match that predicate.
Looks like you're trying to mix dynamic sql and a standard query. That won't work. Your query either has to be all dynamically created and then specially executed or your IN clause has to be inputed with individual arguments which can be done by subqery.
You could do something like:
... AND x.AutoDivision IN
(SELECT Division WHERE Corp = 'GM') ...
OR
... AND x.AutoDivision IN
(SELECT 'Cad' UNION SELECT 'GMC' UNION SELECT 'Sat' UNION SELECT 'Che') ...
Try this:
SELECT
oh.OrderNumber, lg.[lgh_number]
FROM
[dbo].[OrderHeader] oh (NOLOCK)
INNER JOIN
[dbo].[DistrctHeader] lg (NOLOCK) ON oh.[inv_number] = lg.[inv_number]
INNER JOIN
[dbo].[DealerCompany] c (NOLOCK) ON c.cmp_id = LEFT(oh.[ordernumber],3)
INNER JOIN
[dbo].[divisionXREF] x (NOLOCK) ON x.Division = c.comp_revtype
WHERE
oh.ord_number = '113-889257'
AND x.AutoDivision IN
(SELECT 'Cad' UNION SELECT 'GMC' UNION SELECT 'Sat' UNION SELECT 'Che')
AND lg.[lgh_outstatus] IN ('AVL', 'PLN', 'DSP', 'STD', 'PND','CMP')
That is an inline subquery that UNIONs arbitrary strings into a result set. (Take with a grain of salt. I am a long way from a Sql Server interface.)

AND x.AutoDivision IN (#AutoDivision)
--AND x.AutoDivision IN ('Cad', 'Sat', 'GMC', 'Che')
Can you clarify these two lines of code, are they not doing the same thing?

CREATE FUNCTION [dbo].[Split]
(
#String NVARCHAR(4000),
#Delimiter NCHAR(1)
)
RETURNS TABLE
AS
RETURN
(
WITH Split(stpos,endpos)
AS(
SELECT 0 AS stpos, CHARINDEX(#Delimiter,#String) AS endpos
UNION ALL
SELECT endpos+1, CHARINDEX(#Delimiter,#String,endpos+1)
FROM Split
WHERE endpos > 0
)
SELECT 'Id' = ROW_NUMBER() OVER (ORDER BY (SELECT 1)),
'Data' = SUBSTRING(#String,stpos,COALESCE(NULLIF(endpos,0),LEN(#String)+1)-stpos)
FROM Split
)
GO
DECLARE #AutoDivision varchar(50) = NULL
SET #AutoDivision ='Cad, Sat, GMC, Che'
SELECT * FROM divisionXREF P INNER JOIN dbo.SPLIT(ISNULL(#AutoDivision,''),',') as T ON P.lgh_outstatus = CASE T.strval WHEN '' THEN P.PG_CODE ELSE T.strval END

Related

Simple query that should be working is not

I have a simple query:
declare #manual varchar(80) = '''Discount'',''Misc Charges'''
select *
from #Final
where charge_type in (#manual)
Now I've gone as far as verifying my declared variable is setup correctly by using the PRINT command as follows: PRINT '''Discount'',''Misc Charges''' and it in fact returns as I would expect: 'Discount','Misc Charges'.
However, when I run this query, I get no results.
If I instead simply use:
select *
from #Final
where charge_type in ('Discount','Misc Charges')
Then no problem, I get my results. I'm sure I'll kick myself once I get the answer, but as of right now, this is just not making sense. No errors, it's just not giving me my columns without any rows as if there's no data. What am I missing?
Because
IN ('''Discount'',''Misc Charges''')
is the same as
= '''Discount'',''Misc Charges'''
In other words, that is one single string that contains a bunch of escaped string delimiters, not a comma-separated list of individual string values. Which is why you can do this without SQL Server barfing:
PRINT '''Discount'',''Misc Charges''';
What you want is:
declare #manual varchar(80) = 'Discount,Misc Charges';
select f.*
from #Final AS f
INNER JOIN STRING_SPLIT(#manual, ',') AS s
ON f.charge_type = s.value;
However that can fail on compatibility_level < 130, in which case:
declare #manual varchar(80) = 'Discount,Misc Charges';
select f.*
from #Final AS f
INNER JOIN
OPENJSON('["' + REPLACE(#manual, ',', '","') + '"]') AS s
ON f.charge_type = s.value;
In the latter case you can make the query itself a little nicer by using slightly different jacked-up strings in the variable declaration:
declare #manual varchar(80) = '["Discount","Misc Charges"]';
select f.*
from #Final AS f
INNER JOIN
OPENJSON(#manual) AS s ON f.charge_type = s.value;
Or if you are on an older version and you really are hand-crafting these strings inline, you can use a table variable or CTE like #SMor suggested.
Table variable:
DECLARE #d table(str varchar(32));
INSERT #d VALUES('Discount'),('Misc Charges');
SELECT f.*
from #Final AS f
INNER JOIN #d AS d
ON f.charge_type = d.str;
CTE:
;WITH cte AS
(
SELECT str = 'Discount'
UNION ALL
SELECT str = 'Misc Charges'
)
SELECT f.*
from #Final AS f
INNER JOIN cte
ON f.charge_type = cte.str;
If you'll have more values at some point, it tips to writing a table constructor instead of multiple UNION ALLs, e.g.
;WITH cte AS
(
SELECT str FROM
(
VALUES('Discount','Misc Charges')
) AS s(str)
)
SELECT f.*
from #Final AS f
INNER JOIN cte
ON f.charge_type = cte.str;
You can use just use your list of values as comma seperated string & then use STRING_SPLIT.
declare #manual varchar(80) = 'Discount,Misc Charges'
select *from #Final
where charge_type in (SELECT * from STRING_SPLIT(#manual,',))
Here is to to do in SQL Server 2016 onwards.
SQL
DECLARE #manual VARCHAR(80) = 'Discount,Misc Charges';
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, charge_type VARCHAR(30));
INSERT INTO #tbl (charge_type) VALUES
('Discount'),
('No Discount'),
('Misc Charges');
SELECT *
FROM #tbl
WHERE charge_type in (SELECT value FROM STRING_SPLIT(#manual, ','))

Replacing Is Null Or Exist Inner Query Logic to Reduce Stored Procedure Execution Time

My stored procedure is currently using Is Null Or Exist logic combined with an inner query to filter out the records. The stored procedure is converting multiple comma-separated input values to temp tables (in the production scenario, the input record count will be much higher). And the inner query is using these temp tables for filter conditions. Due to the concern over query execution time would like to change the existing inner-query with an alternate (like left join). But need to retain the same Is Null Or Exist logic. Any suggestions?
DECLARE #SelectedOfferes varchar(1000) = 'FLT10,SPL20'
DECLARE #SelectedBrandCode varchar(1000) = '208,406'
DECLARE #CategoryCode varchar(1000) = 'GMOVN2,CELSMR,LCDTV38IN'
CREATE TABLE #SelectedOfferes
(
DiscountCode VARCHAR(20)
)
CREATE TABLE #BrandCode
(
BrandCode VARCHAR(20)
)
CREATE TABLE #CategoryCode
(
CategoryCode VARCHAR(20)
)
IF #SelectedOfferes IS NOT NULL
BEGIN
INSERT INTO #SelectedOfferes
SELECT part
FROM dbo.[FormatTextByDelimiter] (#SelectedOfferes, ',')
END
IF #SelectedBrandCode IS NOT NULL
BEGIN
INSERT INTO #BrandCode
SELECT part
FROM dbo.[FormatTextByDelimiter] (#SelectedBrandCode, ',')
END
IF #CategoryCode IS NOT NULL
BEGIN
INSERT INTO #CategoryCode
SELECT part
FROM dbo.[FormatTextByDelimiter] (#CategoryCode, ',')
END
SELECT *
FROM Products P
INNER JOIN Discount D ON P.DiscountCode = D.DiscountCode
INNER JOIN AvailableBrand AB ON P.BrandCode = AB.BrandCode
INNER JOIN Category C ON P.CategoryCode = C.CategoryCode
WHERE (#SelectedOfferes IS NULL
OR (EXISTS (SELECT 1 FROM #SelectedOfferes OFR
WHERE OFR.DiscountCode = P.DiscountCode)))
AND (#SelectedBrandCode IS NULL
OR (EXISTS (SELECT 1 FROM #BrandCode BC
WHERE BC.BrandCode = P.BrandCode)))
AND (#CategoryCode IS NULL
OR (EXISTS (SELECT 1 FROM #CategoryCode CAT
WHERE CAT.CategoryCode = P.CategoryCode)))
Dynamic SQL version
I have some questions about your string split function, is it set-based or a looping query? If it's not set-based then you should probably replace it with Jeff Moden's DelimitedSplit8K available at http://www.sqlservercentral.com/articles/Tally+Table/72993/ .
The below example should work the same as what you supplied but should be faster since it removes the ORs and the correlated subqueries from the WHERE clause. I'm not a fan of using dynamic SQL but sometimes it is the best way to get the job done. Maybe someone else can come up with a non-dynamic solution that works as well or better.
DECLARE #SelectedOfferes varchar(1000) = 'FLT10,SPL20'
DECLARE #SelectedBrandCode varchar(1000) = '208,406'
DECLARE #CategoryCode varchar(1000) = 'GMOVN2,CELSMR,LCDTV38IN'
CREATE TABLE #SelectedOfferes
(
DiscountCode VARCHAR(20)
)
CREATE TABLE #BrandCode
(
BrandCode VARCHAR(20)
)
CREATE TABLE #CategoryCode
(
CategoryCode VARCHAR(20)
)
IF #SelectedOfferes IS NOT NULL
BEGIN
INSERT INTO #SelectedOfferes
SELECT part
FROM dbo.[FormatTextByDelimiter] (#SelectedOfferes, ',')
END
IF #SelectedBrandCode IS NOT NULL
BEGIN
INSERT INTO #BrandCode
SELECT part
FROM dbo.[FormatTextByDelimiter] (#SelectedBrandCode, ',')
END
IF #CategoryCode IS NOT NULL
BEGIN
INSERT INTO #CategoryCode
SELECT part
FROM dbo.[FormatTextByDelimiter] (#CategoryCode, ',')
END
DECLARE #SQL NVarchar(4000);
SET #SQL = N'SELECT *
FROM Products P
INNER JOIN Discount D ON P.DiscountCode = D.DiscountCode
INNER JOIN AvailableBrand AB ON P.BrandCode = AB.BrandCode
INNER JOIN Category C ON P.CategoryCode = C.CategoryCode'
IF #SelectedOfferes IS NOT NULL
SET #SQL = #SQL + N'
INNER JOIN #SelectedOfferes OFR ON OFR.DiscountCode = P.DiscountCode';
IF #SelectedBrandCode IS NOT NULL
SET #SQL = #SQL + N'
INNER JOIN #BrandCode BC ON BC.BrandCode = P.BrandCode';
IF #CategoryCode IS NOT NULL
SET #SQL = #SQL + N'
INNER JOIN #CategoryCode CAT ON CAT.CategoryCode = P.CategoryCode';
EXEC sys.sp_executesql #stmt = #SQL;
This method doesn't quite do what the OP wanted but is valid in many other cases
I have some questions about your string split function, is it set-based or a looping query? If it's not set-based then you should probably replace it with Jeff Moden's DelimitedSplit8K available at http://www.sqlservercentral.com/articles/Tally+Table/72993/ .
But either way the below change to your last query should help quite a bit. The IS NULL parts aren't needed since it is a LEFT JOIN and the table will be empty if the variable it is built with is NULL, so you get the same result with less work for the engine.
SELECT *
FROM Products P
INNER JOIN Discount D ON P.DiscountCode = D.DiscountCode
INNER JOIN AvailableBrand AB ON P.BrandCode = AB.BrandCode
INNER JOIN Category C ON P.CategoryCode = C.CategoryCode
LEFT JOIN #SelectedOfferes OFR ON OFR.DiscountCode = P.DiscountCode
LEFT JOIN #BrandCode BC ON BC.BrandCode = P.BrandCode
LEFT JOIN #CategoryCode CAT ON CAT.CategoryCode = P.CategoryCode

Best way to join this into a temp table and inner join

Just wondering the best way to put this into a temp table and then join it.
IF EXISTS(SELECT LocId
FROM dbo.Locations WITH (NOLOCK)
WHERE SourceSystem = #SourceSystem
AND LocId IN (SELECT ListVal
FROM etopsuser.fnParseListToTable(#LocIdList, ';')) AND IsHot = 1)
BEGIN
Specifically trying to do it on this line of code
(SELECT ListVal
FROM etopsuser.fnParseListToTable(#LocIdList, ';')) AND IsHot = 1)
The NOLOCK is unrelated
You would create a temporary table just like any other table from a select:
SELECT ListVal
INTO #templist
FROM etopsuser.fnParseListToTable(#LocIdList, ';');
Then you would use it as:
SELECT l.LocId
FROM dbo.Locations l JOIN
#templist tl
ON l.LocId = tl.Listval
WHERE l.SourceSystem = #SourceSystem AND l.IsHot = 1
The best way to pass a list into a procedure is to use a Table Valued Parameter
CREATE TYPE dbo.List AS TABLE (ListVal varchar(255));
IF EXISTS(SELECT 1
FROM dbo.Locations l
WHERE l.SourceSystem = #SourceSystem
AND l.LocId IN (
SELECT ll.ListVal
FROM #LocIdList ll
) AND IsHot = 1)
Notes: Always use table references on every column, especially if subqueries are involved. Never use NOLOCK unless you are prepared for incorrect results. EXISTS ignores its SELECT, so SELECT 1 or SELECT NULL is standard.
Then you can pass in the table variable either from client code depending on language, or in T-SQL like this
DECLARE #list dbo.List;
INSERT #list (ListVal)
VALUES ('SomeValue');
EXEC YourProc #LocIdList = #list;

Convert all rows into different in sql server

I have a stored procedure that is showing a list of doctors and their details based on the sub-department they belong to. Below is the stored proc:
CREATE PROCEDURE SP_BILL_FOOTER_DOCTOR
#subDepartmentId int
AS
BEGIN
SELECT HETC_MST_EMPLOYEE.EMPLOYEE_NAME,
HETC_PAR_EMPLOYEE_TYPE.EMPLOYEE_TYPE_NAME,
HETC_MST_DOCTOR_SPECIALITY.DOCTOR_SPECIALITY_DESCRIPTION,
HETC_MST_SUB_DEPARTMENT.SUB_DEPARTMENT_NAME,
HETC_MST_EMPLOYEE.DOCTOR_SIGNATURE,
CASE WHEN HETC_MST_EMPLOYEE.DOCTOR_SIGNATURE = ''
THEN ''
ELSE ISNULL(SIGNATURE_PATH.DOCUMENT_PATH,'')+ HETC_MST_EMPLOYEE.DOCTOR_SIGNATURE
END AS DOCTOR_SIGNATURE_PIC
FROM HETC_MST_EMPLOYEE
INNER JOIN HETC_PAR_EMPLOYEE_TYPE
ON HETC_PAR_EMPLOYEE_TYPE.EMPLOYEE_TYPE_ID = HETC_MST_EMPLOYEE.EMPLOYEE_TYPE_ID
INNER JOIN HETC_MST_DOCTOR_SPECIALITY
ON HETC_MST_DOCTOR_SPECIALITY.DOCTOR_SPECIALITY_ID = HETC_MST_EMPLOYEE.DOCTOR_SPECIALITY_ID
INNER JOIN HETC_MST_DOCTOR_DEPARTMENT
ON HETC_MST_DOCTOR_DEPARTMENT.EMPLOYEE_ID = HETC_MST_EMPLOYEE.EMPLOYEE_ID
INNER JOIN HETC_MST_SUB_DEPARTMENT
ON HETC_MST_SUB_DEPARTMENT.SUB_DEPARTMENT_ID = HETC_MST_DOCTOR_DEPARTMENT.SUB_DEPARTMENT_ID
LEFT JOIN (SELECT DOCUMENT_PATH
FROM HETC_MST_DOCUMENT_PATH
INNER JOIN HETC_MST_TYPE_OF_ATTACHMENT
ON HETC_MST_DOCUMENT_PATH.TYPE_OF_DOCUMENT_ID = HETC_MST_TYPE_OF_ATTACHMENT.TYPE_OF_DOCUMENT_ID
WHERE HETC_MST_TYPE_OF_ATTACHMENT.TYPE_OF_DOCUMENT_CODE='DSI') AS DOC_SIGNATURE_PIC
ON 1=1
WHERE HETC_MST_SUB_DEPARTMENT.SUB_DEPARTMENT_ID = #subDepartmentId
END
Below is the link of the output that follows when procedure executes :
I want to know is it possible to convert the rows in different column. Like the output has 6 columns and 2 rows, I want all the data in 1 row with 12 columns. Below is the sample output:
It would be of great help if somebody could guide me on how to do it. I have understood that by using Pivot in Sql, I can achieve this, but none I have found to my specific case.
Please have a look at updated code below:
select *, row_number() over(order by employee_name) rownum into #a from (
SELECT HETC_MST_EMPLOYEE.EMPLOYEE_NAME,
HETC_PAR_EMPLOYEE_TYPE.EMPLOYEE_TYPE_NAME,
HETC_MST_DOCTOR_SPECIALITY.DOCTOR_SPECIALITY_DESCRIPTION,
HETC_MST_SUB_DEPARTMENT.SUB_DEPARTMENT_NAME,
HETC_MST_EMPLOYEE.DOCTOR_SIGNATURE,
CASE WHEN HETC_MST_EMPLOYEE.DOCTOR_SIGNATURE = ''
THEN ''
ELSE ISNULL(SIGNATURE_PATH.DOCUMENT_PATH,'')+ HETC_MST_EMPLOYEE.DOCTOR_SIGNATURE
END AS DOCTOR_SIGNATURE_PIC
FROM HETC_MST_EMPLOYEE
INNER JOIN HETC_PAR_EMPLOYEE_TYPE
ON HETC_PAR_EMPLOYEE_TYPE.EMPLOYEE_TYPE_ID = HETC_MST_EMPLOYEE.EMPLOYEE_TYPE_ID
INNER JOIN HETC_MST_DOCTOR_SPECIALITY
ON HETC_MST_DOCTOR_SPECIALITY.DOCTOR_SPECIALITY_ID = HETC_MST_EMPLOYEE.DOCTOR_SPECIALITY_ID
INNER JOIN HETC_MST_DOCTOR_DEPARTMENT
ON HETC_MST_DOCTOR_DEPARTMENT.EMPLOYEE_ID = HETC_MST_EMPLOYEE.EMPLOYEE_ID
INNER JOIN HETC_MST_SUB_DEPARTMENT
ON HETC_MST_SUB_DEPARTMENT.SUB_DEPARTMENT_ID = HETC_MST_DOCTOR_DEPARTMENT.SUB_DEPARTMENT_ID
LEFT JOIN (SELECT DOCUMENT_PATH
FROM HETC_MST_DOCUMENT_PATH
INNER JOIN HETC_MST_TYPE_OF_ATTACHMENT
ON HETC_MST_DOCUMENT_PATH.TYPE_OF_DOCUMENT_ID = HETC_MST_TYPE_OF_ATTACHMENT.TYPE_OF_DOCUMENT_ID
WHERE HETC_MST_TYPE_OF_ATTACHMENT.TYPE_OF_DOCUMENT_CODE='DSI') AS DOC_SIGNATURE_PIC
ON 1=1
WHERE HETC_MST_SUB_DEPARTMENT.SUB_DEPARTMENT_ID = #subDepartmentId )a
declare #iterator int=1
declare #string varchar(max)= ''
declare #string2 varchar(max)= ''
declare #string3 varchar(max)= ''
declare #string4 varchar(max)= ''
declare #exec varchar(max)
while #iterator<=(select max(rownum) from #a)
begin
select #string2=
'['+cast(#iterator as varchar(max))+'].'+ 'EMPLOYEE_NAME'+
',['+cast(#iterator as varchar(max))+'].'+'EMPLOYEE_TYPE_NAME' +
',['+cast(#iterator as varchar(max))+'].'+'DOCTOR_SPECIALITY_DESCRIPTION' +
',['+cast(#iterator as varchar(max))+'].'+'SUB_DEPARTMENT_NAME' +
',['+cast(#iterator as varchar(max))+'].'+'DOCTOR_SIGNATURE'+
',['+cast(#iterator as varchar(max))+'].'+'DOCTOR_SIGNATURE_PIC'
from #a where rownum=#iterator
select #string= #string+#string2
select #string4=
case when #string4='' then
#string4+'['+cast(#iterator as varchar(max))+'].rownum='+cast(#iterator as varchar(max)) else
#string4+' and ['+cast(#iterator as varchar(max))+'].rownum='+cast(#iterator as varchar(max)) end
select #string3= case when #iterator>1 then #string3+' cross join #a ['+ cast(#iterator as varchar(max))+']' else '' end
set #iterator=#iterator+1
end
select #exec = 'select distinct'+ left(#string, len(#string)-1) +' from #a [1] '+#string3+ ' where '+ #string4
exec(''+#exec+'')
This isn't really an answer but a demonstration of how much using aliases can improve the legibility of your queries. Believe it or not this EXACTLY the same thing you posted. I just used aliases so you can read this instead of looking at a wall of text. The only actual change was to use a cross join instead of a left join on 1 = 1.
SELECT e.EMPLOYEE_NAME,
et.EMPLOYEE_TYPE_NAME,
s.DOCTOR_SPECIALITY_DESCRIPTION,
sd.SUB_DEPARTMENT_NAME,
e.DOCTOR_SIGNATURE,
CASE WHEN e.DOCTOR_SIGNATURE = ''
THEN ''
ELSE ISNULL(SIGNATURE_PATH.DOCUMENT_PATH, '') + e.DOCTOR_SIGNATURE
END AS DOCTOR_SIGNATURE_PIC
FROM HETC_MST_EMPLOYEE e
INNER JOIN HETC_PAR_EMPLOYEE_TYPE et ON et.EMPLOYEE_TYPE_ID = e.EMPLOYEE_TYPE_ID
INNER JOIN HETC_MST_DOCTOR_SPECIALITY s ON s.DOCTOR_SPECIALITY_ID = e.DOCTOR_SPECIALITY_ID
INNER JOIN HETC_MST_DOCTOR_DEPARTMENT dd ON dd.EMPLOYEE_ID = e.EMPLOYEE_ID
INNER JOIN HETC_MST_SUB_DEPARTMENT sd ON sd.SUB_DEPARTMENT_ID = dd.SUB_DEPARTMENT_ID
cross join
(
SELECT DOCUMENT_PATH
FROM HETC_MST_DOCUMENT_PATH p
INNER JOIN HETC_MST_TYPE_OF_ATTACHMENT a ON p.TYPE_OF_DOCUMENT_ID = a.TYPE_OF_DOCUMENT_ID
WHERE a.TYPE_OF_DOCUMENT_CODE='DSI'
) AS DOC_SIGNATURE_PIC
WHERE sd.SUB_DEPARTMENT_ID = #subDepartmentId
For the question at hand it is hard to tell what you are really wanting here. Maybe some conditional aggregation in combination with ROW_NUMBER. Or a PIVOT. You would need to post more details for this. Here is a great place to start. http://spaghettidba.com/2015/04/24/how-to-post-a-t-sql-question-on-a-public-forum/

Expand all view-queries in query

I have queries like this:
SELECT
*
FROM vwUsers
LEFT JOIN tblLocations
ON vwUsers.id = tblLocations.owner
Is there an automated way to expand out this query to include the view statement (and any nested view statements)? I'd like to end up with something like:
SELECT * FROM
(SELECT id,name, -- vwUsers expanded into it's defining statement
FROM tblUsers
LEFT JOIN tblNames
ON tblUsers.id = tblNames.id) AS vwUsers
LEFT JOIN tblLocations
ON vwUsers.id = tblLocations.owner
The solution seems clear:
Create a list with all refereed views
Get their definitions
Replace the definitions in your query
Something like this in my environment:
DECLARE #Objects TABLE
(
[ObjectName] SYSNAME
,[Definition] NVARCHAR(MAX)
);
INSERT INTO #Objects ([ObjectName])
VALUES ('[dbo].[SurveyInstancesHistory]')
,('dbo.vw_MystClients');
UPDATE #Objects
SET [Definition] = M.[definition]
FROM #Objects O
INNER JOIN [sys].[objects] OB
ON OBJECT_ID([ObjectName]) = OB.[object_id]
INNER JOIN [sys].[sql_modules] M
ON OBJECT_ID([ObjectName]) = M.[object_id]
WHERE OB.[type] = 'V';
DECLARE #DynamicTSQLStatement NVARCHAR(MAX) = N'
SELECT *
FROM SurveyInstances SI
INNER JOIN [dbo].[SurveyInstancesHistory] SIH
ON SI.[SurveyInstanceID] = SIH.[SurveyInstanceID]
INNER JOIN ProtoSurveys PS
ON SI.[ProtoSurveyID] = PS.[ProtoSurveyID]
INNER JOIN dbo.vw_MystClients MC
ON PS.[ClientID] = MC.[Client<br>ID];'
SELECT #DynamicTSQLStatement = REPLACE(#DynamicTSQLStatement, [ObjectName], '(' + [Definition] + ') AS ' + [ObjectName])
FROM #Objects;
SELECT #DynamicTSQLStatement;
In order this to be automated the following cases must be handled:
we can automatically get the referred objects using regex matches
we can automatically replace the CREATE VIEW .... AS statement using regex
In you need a script that's always working in your example you need to write the regex expressions by yourself as people are creating views with different syntax. As the above can be used and edited by hand in order to run, a very complex script can be created depending on your needs.
Strongly recommenced to implement the String Utility Functions Sample in order to get regex support in T-SQL.