Join with dynamic pivot - sql

Followed up by a new question, that contains the question as text, not as an image like this one:
Join with dynamic pivot (version 2)
(This question is an image. Right click on "I have some table with value". :)
alt text http://img36.imageshack.us/img36/4853/77517349.gif
The query should automaticly work if a new position record is added. Thanks you

SELECT
c.CategoryId AS CID,
c.CategoryName,
ISNULL(t.CategoryOrder, 0) AS [Top],
ISNULL(l.CategoryOrder, 0) AS [Left],
ISNULL(r.CategoryOrder, 0) AS [Right]
FROM
Category c
LEFT JOIN CategoryPosition t ON t.CategoryId = c.CategoryId
AND t.PositionId = 1
LEFT JOIN CategoryPosition l ON l.CategoryId = c.CategoryId
AND l.PositionId = 2
LEFT JOIN CategoryPosition r ON r.CategoryId = c.CategoryId
AND r.PositionId = 3

Messy, but it works
select c.categoryid,c.categoryname
,COALESCE((select top 1 categoryorder from categoryposition where categoryid=c.categoryid and positionid=1),0) as [top]
,COALESCE((select top 1 categoryorder from categoryposition where categoryid=c.categoryid and positionid=2),0) as [left]
,COALESCE((select top 1 categoryorder from categoryposition where categoryid=c.categoryid and positionid=3),0) as [right]
from categoryposition cp,category c
where cp.categoryid=c.categoryid
group by c.categoryid,c.categoryname
order by 1
Two things to keep in mind. If you can ensure that there is at most one position for each categoryposition then you can remove the top 1, but the subquery must return 1 row o nothing for it to work.

Since you want the cross tab query to be dynamic based on the contents of Position table then I recommend that you dynamicly generate the SQL at runtime.
-- Start with Query frame
DECLARE #Query NVARCHAR(4000)
SET #Query = '
Select
Category.CategoryID,
Category.CategoryName
<DYNAMICQUERY>
From CategoryPosition
Inner Join Category ON Category.CategoryID = CategoryPosition.CategoryID
Group By Category.CategoryID, Category.CategoryName';
SELECT #Query;
-- Build the dynamic part of query
DECLARE #DynamicQuery VARCHAR(1024)
DECLARE #PositionCol VARCHAR(256)
DECLARE dynamic_sql CURSOR FOR
SELECT ',MAX(CASE WHEN CategoryPosition.PositionID = '+CAST(PositionID AS varchar(10)) +' THEN CategoryPosition.CategoryOrder ELSE 0 END) AS ['+PositionName+']'
From Position
OPEN dynamic_sql
FETCH NEXT FROM dynamic_sql
INTO #PositionCol
SELECT #DynamicQuery = #PositionCol;
WHILE ##FETCH_STATUS = 0
BEGIN
FETCH NEXT FROM dynamic_sql
INTO #PositionCol
SELECT #DynamicQuery = #DynamicQuery+#PositionCol;
END
CLOSE dynamic_sql
DEALLOCATE dynamic_sql
SELECT #Query = REPLACE(#Query, '<DYNAMICQUERY>', #DynamicQuery)
-- Execute the Query
EXECUTE sp_executesql #Query

Related

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

While executing my stored procedure, I'm getting this error while my input is multiple values [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
This is my SP.
I'm getting this error - "Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression."
enter code here
ALTER PROCEDURE GetToDoDetails
#ClientID VARCHAR(MAX) = NULL
AS
DECLARE #Sql VARCHAR(MAX)
SET #ClientID = REPLACE(#ClientID,',',''',''')
SET #Sql=
'SELECT
C.ClientID,
C.ClientToDoID,
C.AssignedToID,
C.ToBeCompletedBy,
C.ToDoTypeID,
S.UDDescription,
(CL.LastName +'',''+ CL.FirstName) "Client Name",
(Select count(ClientID) from c_ToDo WHERE ClientID IN (''' + #ClientID+''') GROUP BY ClientID) "CountRow"
FROM c_ToDo C
INNER JOIN s_UserDefinedOptions S ON C.ToDoTypeID = S.UDID
INNER JOIN c_Client CL ON C.ClientID = CL.ClientID
WHERE
C.ClientID IN (''' + #ClientID + ''')
ORDER BY C.ClientID ASC'
EXEC (#Sql)
GO
If I write
EXEC GetToDoDetails '1566'
, I'm getting this result(refer image)
Now if I write
EXEC GetToDoDetails '1566,1697'
It is showing the error which I told about.
After Adding TOP 1 in my subquery as
(Select TOP 1 count(ClientID) from c_ToDo WHERE ClientID IN (''' + #ClientID + ''')
I'm getting the count for first record only for different clientIDs(1566 & 1697).(refer image)
After the 45th record for ClientID=1566(total row count is 45 for 1566),
I want the count to change for ClientID=1697(which is 63).
I don't know how to approach this. I'm a newbie. Please help.
There's some guess work in there, however, SQL Injection is not your friend. That needs to go, NOW. I've therefore used a Table Type Parameter instead.
In regards to the error, that was due to the statement:
(Select count(ClientID) from c_ToDo WHERE ClientID IN (''' + #ClientID+''') GROUP BY ClientID) "CountRow"
This'll return multiple rows if you had more than one value in #ClientID. Also, the quote operator in SQL Server for an object is a bracket ([]), not double quotes (").
Anyway, this is a guess, but this should get you on the right path (I hope):
CREATE TYPE ClientList AS TABLE (ClientID int); --Datatype is GUESSED
GO
CREATE PROCEDURE GetToDoDetails #Client ClientList READONLY
AS
SELECT C.ClientID,
C.ClientToDoID,
C.AssignedToID,
C.ToBeCompletedBy,
C.ToDoTypeID,
S.UDDescription,
(CL.LastName + ',' + CL.FirstName) AS [Client Name],
COUNT(C.ClientID) OVER (PARTITION BY C.ClientID) AS [CountRow] --Total guess here
--If this is meant to just be a count of EVERY row, remove the PARTITION BY clause (so just OVER())
FROM c_ToDo C
INNER JOIN s_UserDefinedOptions S ON C.ToDoTypeID = S.UDID
INNER JOIN c_Client CL ON C.ClientID = CL.ClientID
WHERE EXISTS (SELECT 1 FROM #Client e WHERE C.ClientID = e.ClientID) --Changed from IN to EXISTS
ORDER BY C.ClientID ASC;
GO
It is not ideal to have a subquery in select statement for count, In your query you are getting multiple values as client id has multiple values, I would prefer to bring it down in join statement. Print #sql should work to check if statement is valid. This will do the trick for you
DECLARE #ClientID VARCHAR(MAX) = NULL
DECLARE #Sql VARCHAR(MAX)
SET #ClientID = REPLACE('1566,1697,2467',',',''',''')
SET #Sql=
'SELECT
C.ClientID,
C.ClientToDoID,
C.AssignedToID,
C.ToBeCompletedBy,
C.ToDoTypeID,
S.UDDescription,
(CL.LastName +'',''+ CL.FirstName) "Client Name",
"CountRow"
FROM c_ToDo C
INNER JOIN s_UserDefinedOptions S ON C.ToDoTypeID = S.UDID
INNER JOIN c_Client CL ON C.ClientID = CL.ClientID
INNER JOIN (Select count(*) CountRow,ClientID from c_ToDo WHERE ClientID IN (''' + #ClientID+''') GROUP BY ClientID) CO
on C.ClientID = CO.ClientID
WHERE
C.ClientID IN (''' + #ClientID + ''')
ORDER BY C.ClientID ASC'
PRINT (#Sql)
Your SP:
ALTER PROCEDURE GetToDoDetails
#ClientID VARCHAR(MAX) = NULL
AS
BEGIN
DECLARE #Sql VARCHAR(MAX)
SET #ClientID = REPLACE(#ClientID,',',''',''')
SET #Sql=
'SELECT
C.ClientID,
C.ClientToDoID,
C.AssignedToID,
C.ToBeCompletedBy,
C.ToDoTypeID,
S.UDDescription,
(CL.LastName +'',''+ CL.FirstName) "Client Name",
"CountRow"
FROM c_ToDo C
INNER JOIN s_UserDefinedOptions S ON C.ToDoTypeID = S.UDID
INNER JOIN c_Client CL ON C.ClientID = CL.ClientID
INNER JOIN (Select count(*) CountRow,ClientID from c_ToDo WHERE ClientID IN (''' + #ClientID+''') GROUP BY ClientID) CO
on C.ClientID = CO.ClientID
WHERE
C.ClientID IN (''' + #ClientID + ''')
ORDER BY C.ClientID ASC'
PRINT (#Sql)
EXEC (#Sql)
END

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/

Using Local Variable Value As Query Criteria SQL Server

Background: I want to compare each column in all tables for two Person records by looping through all possible columns. I then want to run a common table expression which uses each column as it loops, and if the second Person column is NULL, I want it to update with the value of the first Person column, for all duplicate records based on specific criteria.
This will essentially loop through all duplicates and update them to match, prior to deleting one.
I am running a stored procedure which loops through table columns. I would like to use those columns in a query. Here is what I have:
declare table_columns cursor local dynamic for
select BaseTable,
DBColumn
from viewTableInfo
declare #BaseTable nvarchar (100)
declare #DBColumn nvarchar (100)
open table_columns
while (1 = 1)
begin
fetch next from table_columns into #BaseTable, #DBColumn
if (##FETCH_STATUS <> 0 ) break
;with CTE as
(
select firstName,
lastName,
#DBColumn AS Column,
rn = ROW_NUMBER()OVER(PARTITION BY firstName, lastName ORDER BY pID)
from Person p
inner join Company c ON c.pID = p.pID -- joined because variable may be column from Company table.
where p.pID in (1, 2)
)
select destinationProperty = case
when c1.Column = c2.Column then c2.Column
when c2.Column IS NULL THEN c1.Column
ELSE c2.Column END
from cte c1
inner join cte c2 on c1.firstName = c2.firstName and c1.lastName = c2.LastName and c2.rn = c1.rn + 1
When I run this, I get zero records in the result set because the common table expression is selecting the value of the variable #DBColumn, which, for each loop, is the actual Column Name.
What I need is to be able to use the actual Column name in the query and get the value of that column for each pID in the result set.
Is this possible?
Not sure of exact requirement to use cursor and dynamic column names here, but you can get the required functionality using dynamic SQL.
Changed the loop not to use 1=1 , instead to check for cursor status.
declare table_columns cursor local dynamic for
select BaseTable,
DBColumn
from viewTableInfo
declare #BaseTable nvarchar (100)
declare #DBColumn nvarchar (100)
declare #query nvarchar(max)
open table_columns
fetch next from table_columns into #BaseTable, #DBColumn
WHILE ##FETCH_STATUS = 0
begin
set #query =';with CTE as
(
select firstName,
lastName,
' + #DBColumn + ' AS Column,
rn = ROW_NUMBER()OVER(PARTITION BY firstName, lastName ORDER BY pID)
from Person p
inner join Company c ON c.pID = p.pID -- joined because variable may be column from Company table.
where p.pID in (1, 2)
)
select destinationProperty = case
when c1.Column = c2.Column then c2.Column
when c2.Column IS NULL THEN c1.Column
ELSE c2.Column END
from cte c1
inner join cte c2 on c1.firstName = c2.firstName and c1.lastName = c2.LastName and c2.rn = c1.rn + 1'
exec sp_executesql #query
fetch next from table_columns into #BaseTable, #DBColumn
end

insert value from one table to another checking id

I have 2 tables.All the ids are include in table one (Tbl_Distributor). 2nd table have all the names.
I want to add all the names to first table according to id.
My select query as below.
INSERT INTO dbo.Tbl_Distributor(Giv_Name) where dealercode= a.dealercode
SELECT a.dealercode,d.nameinfull
FROM dealerplacement a,dealer d
where a.dealercode= d.dealercode
order by a.dealercode ASC
This returns nameinfull and dealercode. I want to add this nameinfull to Tbl_Distributor .
Please help me to solve this issue.
UPDATE R
SET Giv_Name = D.FirstName
FROM
dbo.Tbl_Distributor R
INNER JOIN dbo.Dealer D
ON R.Dis_ID = D.DealerCode
You cannot use INSERT here. You need to use update. I'd do such a task using cursors.
declare #id int, #name varchar(1000)
DECLARE c CURSOR FOR
SELECT a.dealercode,d.nameinfull
FROM dealerplacement a,dealer d
where a.dealercode= d.dealercode
order by a.dealercode ASC
OPEN c
FETCH NEXT FROM c
INTO #id, #name
WHILE ##FETCH_STATUS = 0
BEGIN
update Tbl_Distributor set Giv_Name = #name where dealercode = #id
FETCH NEXT FROM c
INTO #id, #name
end
CLOSE c;
DEALLOCATE c;
Also, I'd use join in the select statement:
SELECT a.dealercode,d.nameinfull
FROM dealerplacement a inner join dealer d
on a.dealercode= d.dealercode
order by a.dealercode ASC