SQL Server: Dynamically Pivot Temp Table (Dynamic SQL) - sql-server

I want to Dynamically pivot my #Tempproj table. This table consists of multiple CTE's that I insert into this #Tempproj. Now I want to Pivot this temptable, however I currently can only do it now when I create a Physical table instead of a Temporary one.
When I run it with the following query it says:
Must declare the table variable "#Tempproj"
I don't know how to mix this SQL with Dynamic SQL correctly.
First I declare a temp table, quite a long statement, and all the way below is the Dynamic SQL Pivot query I use.
CREATE TABLE #Tempproj
(
[ProjKey] nvarchar(250) NULL
,[Lvl3] nvarchar(250) NULL
,[Lvl2] nvarchar(250) NULL
,[Lvl1] nvarchar(250) NULL
,[Element ID] nvarchar(250) NULL
,[Activiteit] nvarchar(250) NULL
,[Doel] nvarchar(250) NULL
,[Activiteitsnummer] nvarchar(250) NULL
,[Begindatum/-tijd] date NULL
,[Einddatum/-tijd] date NULL
,[Status projectfase] nvarchar(250) NULL
,[Afsluitingsdatum/-tijd] date NULL
,[Projectactiviteit] nvarchar(250) NULL
,[VerantwoordelijkeId] nvarchar(250) NULL
,[Verantwoordelijke] nvarchar(250) NULL
,[Categorie] nvarchar(250) NULL
,[Prioriteit] nvarchar(250) NULL
,[DataAreaID] nvarchar(250) NULL
);
WITH cteP AS (
SELECT
[NAME]
,ELEMENTNUMBER
,PARENTELEMENTNUMBER
,PathID = CAST(ELEMENTNUMBER AS VARCHAR(MAX))
,DATAAREAID
FROM HIERARCHYTREETABLE
WHERE NULLIF(PARENTELEMENTNUMBER, '') IS NULL
UNION All
SELECT
[NAME] = r.[NAME]
,ELEMENTNUMBER = r.ELEMENTNUMBER
,PARENTELEMENTNUMBER = r.PARENTELEMENTNUMBER
,PathID = p.PathID+CONCAT(',',CAST(r.ELEMENTNUMBER AS VARCHAR(MAX)))
,DATAAREAID = r.DATAAREAID
FROM HIERARCHYTREETABLE r
JOIN cteP p ON r.PARENTELEMENTNUMBER = p.ELEMENTNUMBER
AND r.DATAAREAID = p.DATAAREAID
)
,
cteP2 AS (
SELECT
B.Lvl3
,B.Lvl2
,B.Lvl1
,HIERARCHYTREETABLE.ELEMENTNUMBER AS 'Element ID'
,HIERARCHYTREETABLE.[NAME] AS 'Activiteit'
,SMMACTIVITIES.PURPOSE AS 'Doel'
,SMMACTIVITIES.ACTIVITYNUMBER AS 'Activiteitsnummer'
,SMMACTIVITIES.STARTDATETIME AS 'Begindatum/-tijd'
,NULLIF(SMMACTIVITIES.ENDDATETIME, '') AS 'Einddatum/-tijd'
,CASE WHEN SMMACTIVITIES.CLOSED = 1 THEN 'Gesloten' ELSE 'Open' END AS 'Status projectfase'
,NULLIF(SMMACTIVITIES.ACTUALENDDATETIME, '') AS 'Afsluitingsdatum/-tijd'
,SMMACTIVITIES.PROJACTID AS 'Projectactiviteit'
,SMMACTIVITIES.RESPONSIBLEEMPLOYEE AS 'VerantwoordelijkeId'
,DIRPARTYTABLE.[NAME] AS 'Verantwoordelijke'
,CASE SMMACTIVITIES.CATEGORY
WHEN 0 THEN 'Afspraak'
WHEN 1 THEN 'Taak'
WHEN 2 THEN 'Actie'
WHEN 3 THEN 'Melding'
END AS Categorie
,CASE SMMACTIVITIES.TASKPRIORITY
WHEN 0 THEN 'Normaal'
WHEN 1 THEN 'Laag'
WHEN 2 THEN 'Hoog'
END AS Prioriteit
,HIERARCHYTREETABLE.DATAAREAID
FROM HIERARCHYTREETABLE
LEFT JOIN cteP
ON cteP.ELEMENTNUMBER = HIERARCHYTREETABLE.ELEMENTNUMBER
AND cteP.DATAAREAID = HIERARCHYTREETABLE.DATAAREAID
CROSS Apply (
SELECT Lvl1 = xDim.value('/x[3]','varchar(50)')
,Lvl2 = xDim.value('/x[2]','varchar(50)')
,Lvl3 = xDim.value('/x[1]','varchar(50)')
,Lvl4 = xDim.value('/x[4]','varchar(50)')
FROM ( VALUES (CAST('<x>' + REPLACE(PathID,',','</x><x>')+'</x>' AS xml))) B(xDim)
) B
LEFT JOIN SMMACTIVITIES
ON SMMACTIVITIES.RECID = HIERARCHYTREETABLE.REFRECID
AND SMMACTIVITIES.DATAAREAID = HIERARCHYTREETABLE.DATAAREAID
LEFT JOIN EMPLTABLE
ON SMMACTIVITIES.RESPONSIBLEEMPLOYEE = EMPLTABLE.EMPLID
LEFT JOIN DIRPARTYTABLE
ON DIRPARTYTABLE.PARTYID = EMPLTABLE.PARTYID
AND DIRPARTYTABLE.DATAAREAID = EMPLTABLE.DATAAREAID
)
INSERT INTO #Tempproj(
[ProjKey],Lvl1,Lvl2,Lvl3,[Element ID]
,Activiteit,Doel,Activiteitsnummer,[Begindatum/-tijd],[Einddatum/-tijd],[Status projectfase]
,[Afsluitingsdatum/-tijd],Projectactiviteit,VerantwoordelijkeId
,Verantwoordelijke,Categorie,Prioriteit,DataAreaID)
SELECT
PROJTABLE.PROJID + '-' + PROJTABLE.DATAAREAID AS 'ProjKey'
,cteP2.*
FROM CteP2
LEFT JOIN HIERARCHYTREETABLE
ON HIERARCHYTREETABLE.ELEMENTNUMBER = CteP2.Lvl3
AND HIERARCHYTREETABLE.DATAAREAID = CteP2.DataAreaId
LEFT JOIN PROJTABLE
ON PROJTABLE.PROJID = HIERARCHYTREETABLE.[NAME]
AND PROJTABLE.DATAAREAID = HIERARCHYTREETABLE.DATAAREAID
WHERE Activiteit NOT LIKE 'MLD%'
AND Activiteit NOT LIKE 'O-%'
AND Activiteit NOT LIKE 'OTR%'
AND SUBSTRING(Activiteit, 1, 1) NOT IN ('1','2','3','4','5','6','7','8','9');
DECLARE #Columns as VARCHAR(MAX)
SELECT
#Columns = COALESCE(#Columns + ', ','') + QUOTENAME(Activiteit)
FROM
(SELECT DISTINCT Activiteit FROM #Tempproj
) AS B
ORDER BY B.Activiteit
DECLARE #SQL as VARCHAR(MAX)
SET #SQL = 'SELECT ProjKey, ' + #Columns + '
FROM
(
SELECT T.ProjKey,
T.Activiteit,
T.[Begindatum/-tijd]
FROM #Tempproj T
) as PivotData
PIVOT
(
max([Begindatum/-tijd])
FOR Activiteit IN (' + #Columns + ')
) AS PivotResult
ORDER BY ProjKey'
EXEC (#SQL)
Then when I run the query, it says that I haven't declared my #Tempproj table yet.
Now I see that I mix up SQL with Dynamic SQL, but I don't know how to fix this giant statement into this.
Any suggestions what I could do here?
EDIT: Table Variable replaced with an actual Temporary Table.

Related

result of one stored procedure to input for Query showing null

I wrote two stored procedures
ALTER PROCEDURE [dbo].[GetPhysicalChildNodesAsString]
-- Add the parameters for the stored procedure here
#Book varchar(50),
#Vertical varchar(50)
AS
BEGIN
DECLARE #results nvarchar(max)
;WITH cte AS
(
SELECT a.BookID, a.ParentBookID, a.BookName
FROM DimBook a
WHERE BookName = #Book
UNION ALL
SELECT a.BookID, a.ParentBookID, a.BookName
FROM DimBook a JOIN cte c ON a.ParentBookID = c.BookID
and HighPortfolioID = ( select PortfolioID from portfolioMaster where PortfolioName = #Vertical and PortfolioType='HighPortfolio')
)
select #results = coalesce(#results + ',', '')+'''' + convert(varchar(max),BookName)+''''
from cte Where Len(BookName) < 20
select #results as Book
END
Above stored Proc returns below string
'Physical','Anish Vohra','Sandeep Bajoria','Nirav Desai','Sushil Mohta','Sahil Pasad','G R Poddar','Direct','Sales Broker','Internal Transfer','Sprint','Murji Meghan','Intra Oils & Fats','GGN','GGN1','GGN2','Book1','Book2','Book 3','Book4','Book5','Comglobal','Sunvin','PVOC','Afro Asian'
DECLARE #BooksList varchar(max)
DECLARE #t table(BookNames varchar(max) )
INSERT #t(BookNames)
EXEC #BooksList = GetPhysicalChildNodesAsString 'Physical','Enterprise'
SELECT #BooksList = BookNames FROM #t
select #BooksList as 'books'
select * from DimBook where BookName IN(select #BooksList as 'books') ----> reults only header of table Only. But if pass result string directly like below it is working. can you help me for why above query is not working
select * from DimBook where BookName IN('Physical','Anish Vohra','Sandeep Bajoria','Nirav Desai','Sushil Mohta','Sahil Pasad','G R Poddar','Direct','Sales Broker','Internal Transfer','Sprint','Murji Meghan','Intra Oils & Fats','GGN','GGN1','GGN2','Book1','Book2','Book 3','Book4','Book5','Comglobal','Sunvin','PVOC','Afro Asian') ----> getting correctly.

Remove additional delimeter from records

I am using STUFF function to retrieve multiple row values to a column.
ALTER PROCEDURE [dbo].[PrintOutlettoOutletTransfer]
#TransferCode varchar(20),
#token nvarchar(50)
AS
BEGIN
DECLARE #Isprint AS int
DECLARE #user AS VARCHAR(50)
DECLARE #PcIp AS VARCHAR(50)
DECLARE #PcName AS VARCHAR(50)
DECLARE #AditUserName AS VARCHAR(100)
DECLARE #outlet AS VARCHAR(100)
DECLARE #ServerName AS VARCHAR(200)
SET #user = ''
-- Retrive data from user login history from Tocken
SELECT
#user = UserLogInHistory.UserId,
#PcIp = LogInIp,
#outlet=OutletCode,
#ServerName = ServerId,
#AditUserName = Users.UserFullName
from UserLogInHistory
inner join Users on Users.UserId = UserLogInHistory.UserId
where UserTokenId = #token;
SELECT
ISNULL(InventoryTransferHeader.TransferCode,'') AS 'TransferId',
ISNULL(InventoryTransferHeader.TransferDate,'') AS 'TransferDate',
ISNULL(InventoryTransferLine.ItemCode,'') AS 'ItemCode',
ISNULL(InventoryTransferLine.ItemDescription,'') AS 'ItemDescription',
ISNULL(InventoryTransferLine.Qty,'') AS 'Qty',
STUFF((SELECT InventoryTransferSerials.SerialNo + ' / '
FROM InventoryTransferSerials
WHERE InventoryTransferSerials.ItemCode = InventoryTransferLine.ItemCode
AND InventoryTransferSerials.TransferCode = InventoryTransferHeader.TransferCode
FOR XML PATH('')),1,1,'') AS 'SN',
ISNULL(InventoryStatus.Description,'') AS 'InventoryStatus',
ISNULL(InventoryTransferHeader.FromOutlet,'') AS 'outletFrom' ,
ISNULL(F.OutletDesc,'') AS 'fromOutletsDesc',
ISNULL(InventoryTransferHeader.TOOutlet,'') AS 'outletTO' ,
ISNULL(T.OutletDesc,'') AS 'toOutletsDesc'
FROM InventoryTransferHeader
INNER JOIN
Outlets F ON InventoryTransferHeader.FromOutlet = F.OutletCode
INNER JOIN
Outlets T ON InventoryTransferHeader.ToOutlet = T.OutletCode
LEFT OUTER JOIN
InventoryStatus on InventoryStatus.StatusCode = InventoryTransferHeader.InventoryStatus
LEFT OUTER JOIN
InventoryTransferLine ON InventoryTransferLine.TransferCode = InventoryTransferHeader.TransferCode
WHERE (InventoryTransferHeader.TransferCode = #TransferCode OR #TransferCode = '') AND (InventoryStatus.StatusCode = 1 OR InventoryStatus.StatusCode = 2)
--- Insert Values to Audit table
INSERT INTO PrintHistory
([DocType],[Reference],[AuditOutlet],[AuditUser],[AuditDate],[AuditType],[AuditIp],[AuditPc],[AuditUserName])
values
('OutletToOutletInventoryTransfer',#TransferCode,#outlet,#user,GETDATE(),'1',#PcIp,#ServerName,#AditUserName);
UPDATE InventoryTransferHeader
SET InventoryTransferHeader.[Print] = 1,
InventoryTransferHeader.[PrintUser] = #user,
InventoryTransferHeader.[PrintDate] = GETDATE()
WHERE InventoryTransferHeader.TransferCode = #TransferCode AND InventoryTransferHeader.[Print] = 0;
END
It gives an output as below.
0000227 / 10000228 / 10000229 / 10000230 / 10000231 /
I want to remove the additional "/" from records.
Please help.
One option to remove a single trailing forward slash at the end is to wrap your current SELECT in a subquery and use LEFT:
SELECT LEFT(t.SN, LEN(t.SN) - 1)
FROM
(
SELECT STUFF((SELECT InventoryTransferSerials.SerialNo + ' /'
FROM InventoryTransferSerials
WHERE InventoryTransferSerials.ItemCode =
InventoryTransferLine.ItemCode AND
InventoryTransferSerials.TransferCode =
InventoryTransferHeader.TransferCode
FOR XML PATH('')), 1, 1, '') AS SN
FROM yourTable
) t

Not Exists not playing well with multiple columns

This has to be something simple that I have just missed...
I've got a temp table say this:
CREATE TABLE #tsa
(
AttendeeID int,
SurveyID int,
TrainingAttendeeID int
)
I get a single record using TOP 1 with something similar to this:
SELECT
TOP 1
#AttendeeID=ta.AttendeeID,
#SurveyID=ts.SurveyID,
#TrainingAttendeeID = ta.TrainingAttendeeID
FROM
TrainingAttendee ta
INNER JOIN
[User] u
ON
u.UserID= ta.AttendeeID
INNER JOIN
[Training] t
ON
t.TrainingID = ta.TrainingID
INNER JOIN
[TrainingSet] ts
ON
ts.TrainingSetID = t.TrainingSetID
WHERE
ta.AttendedTraining = 1
AND ta.ConfirmAttendedEmailOn IS NOT NULL
--only get people who didn't fill out the survey
AND NOT EXISTS (SELECT * FROM SurveyTaken st WHERE st.AddedByUserID = ta.AttendeeID AND st.SurveyID = ts.SurveyID)
ORDER BY
ta.AttendeeID,
ts.SurveyID
As soon as I get this one record I store it into my temp table as such:
--insert into our temp table
INSERT INTO #tsa(AttendeeID, SurveyID, TrainingAttendeeID)
VALUES(#AttendeeID, #SurveyID, #TrainingAttendeeID)
Then I need to go through this whole procedure of checking some data and sending an email...as soon as that email is sent I need to pick up the next record not including the record I had previously...So without showing too much code:
WHILE SomeCondition
BEGIN
--do some thing...
--pick up next one
--grab next one
SELECT
TOP 1
#AttendeeID = ta.AttendeeID,
#SurveyID=ts.SurveyID,
#TrainingAttendeeID=ta.TrainingAttendeeID
FROM
TrainingAttendee ta
INNER JOIN
[User] u
ON
u.UserID= ta.AttendeeID
INNER JOIN
[Training] t
ON
t.TrainingID = ta.TrainingID
INNER JOIN
[TrainingSet] ts
ON
ts.TrainingSetID = t.TrainingSetID
WHERE
(
--same where as original
ta.AttendedTraining = 1
AND (ta.ConfirmAttendedEmailOn IS NOT NULL)
AND (NOT EXISTS (SELECT * FROM SurveyTaken st WHERE st.AddedByUserID = ta.AttendeeID AND st.SurveyID = ts.SurveyID))
--adding the piece such that we compare against the temp table...
AND (NOT EXISTS (SELECT * FROM #tsa tempS WHERE tempS.AttendeeID = ta.AttendeeID AND tempS.SurveyID = ts.SurveyID AND tempS.TrainingAttendeeID = ta.TrainingAttendeeID))
)
ORDER BY
ta.AttendeeID,
ts.SurveyID
--insert into our temp table
INSERT INTO #tsa(AttendeeID, SurveyID, TrainingAttendeeID)
VALUES(#AttendeeID, #SurveyID, #TrainingAttendeeID)
END
Notice the where condition inside of this..I've added one more AND...namely:
--adding the piece such that we compare against the temp table...
AND (NOT EXISTS (SELECT * FROM #tSa tempS WHERE tempS.AttendeeID = ta.AttendeeID AND tempS.SurveyID = ts.SurveyID AND tempS.TrainingAttendeeID = ta.TrainingAttendeeID))
Just to ensure I am not reusing the record I already processed in my temp table...and you'll notice I reinsert into my temp table at the end as well...
--insert into our temp table
INSERT INTO #tsa(AttendeeID, SurveyID, TrainingAttendeeID)
VALUES(#AttendeeID, #SurveyID, #TrainingAttendeeID)
Every time I run this stored procedure it goes on infinitly and so I believe something is wrong with my condition at this point. I'm having a brain fart..or maybe there is just too much noise in the office. What am I missing here? I placed a print statement and it keeps processing the same record...so something tells me this last condition in my where clause is incorrect.
Edit
Here's the entire procedure...My issue is the record set only has one record in it...But the sproc continues to process this same record
PROCEDURE ScriptSendTrainingSurveyReminders
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
DECLARE #AttendeeID int
DECLARE #TrainingAttendeeID int
DECLARE #SurveyID int
DECLARE #Message nvarchar(MAX)
DECLARE #Subject nvarchar(255)
CREATE TABLE #tSa
(
AttendeeID int,
SurveyID int,
TrainingAttendeeID int
)
SELECT
TOP 1
#AttendeeID=ta.AttendeeID,
#SurveyID=ts.SurveyID,
#TrainingAttendeeID = ta.TrainingAttendeeID
FROM
TrainingAttendee ta
INNER JOIN
[User] u
ON
u.UserID= ta.AttendeeID
INNER JOIN
[Training] t
ON
t.TrainingID = ta.TrainingID
INNER JOIN
[TrainingSet] ts
ON
ts.TrainingSetID = t.TrainingSetID
WHERE
ta.AttendedTraining = 1
AND ta.ConfirmAttendedEmailOn IS NOT NULL
--only get people who didn't fill out the survey
AND NOT EXISTS (SELECT * FROM SurveyTaken st WHERE st.AddedByUserID = ta.AttendeeID AND st.SurveyID = ts.SurveyID)
ORDER BY
ta.TrainingAttendeeID,
ta.AttendeeID,
ts.SurveyID
--insert into our temp table
INSERT INTO #tSa(AttendeeID, SurveyID, TrainingAttendeeID)
VALUES(#AttendeeID, #SurveyID, #TrainingAttendeeID)
WHILE #TrainingAttendeeID IS NOT NULL AND #AttendeeID IS NOT NULL AND #SurveyID IS NOT NULL
BEGIN
DECLARE #TrainingID int
DECLARE #Title nvarchar(50)
DECLARE #StartDateTime nvarchar(50)
DECLARE #EndDateTime nvarchar(50)
DECLARE #FullName nvarchar(255)
DECLARE #EmailAddress nvarchar(255)
DECLARE #Description nvarchar(MAX)
--get the one record we are on...
SELECT
#TrainingID = t.TrainingID,
#Title = t.Title,
#StartDateTime = CAST(CONVERT(DATE, t.StartDate) AS VARCHAR(50)) + ' ' + CAST(t.StartTimeHours AS VARCHAR(50)) + ':' + CAST(CASE WHEN LEN(t.StartTimeMinutes)=1 THEN CAST(t.StartTimeMinutes AS VARCHAR(50)) + '0' ELSE CAST(t.StartTimeMinutes AS VARCHAR(50)) END AS VARCHAR(50)) + ' ' + CAST(t.StartTimeAMorPM AS VARCHAR(50)),
#EndDateTime = CAST(CONVERT(DATE, t.EndDate) AS VARCHAR(50)) + ' ' + CAST(t.EndTimeHours AS VARCHAR(50)) + ':' + CAST(CASE WHEN LEN(t.EndTimeMinutes)=1 THEN CAST(t.EndTimeMinutes AS VARCHAR(50)) + '0' ELSE CAST(t.EndTimeMinutes AS VARCHAR(50)) END AS VARCHAR(50)) + ' ' + CAST(t.EndTimeAMorPM AS VARCHAR(50)),
#Description = t.DescriptionHTML,
#FullName = u.FullName,
#EmailAddress = u.EmailAddress
FROM
Training t
INNER JOIN
TrainingAttendee ta
ON
t.TrainingID = ta.TrainingID
INNER JOIN
[User] u
ON
u.UserID = ta.AttendeeID
WHERE
ta.TrainingAttendeeID = #TrainingAttendeeID
IF #EmailAddress IS NOT NULL
BEGIN
--Email goes out here....
END
--grab next one
SELECT
TOP 1
#AttendeeID = ta.AttendeeID,
#SurveyID=ts.SurveyID,
#TrainingAttendeeID=ta.TrainingAttendeeID
FROM
TrainingAttendee ta
INNER JOIN
[User] u
ON
u.UserID= ta.AttendeeID
INNER JOIN
[Training] t
ON
t.TrainingID = ta.TrainingID
INNER JOIN
[TrainingSet] ts
ON
ts.TrainingSetID = t.TrainingSetID
WHERE
(
--same where as original
(ta.AttendedTraining = 1)
AND (ta.ConfirmAttendedEmailOn IS NOT NULL)
AND (NOT EXISTS (SELECT * FROM SurveyTaken st WHERE st.AddedByUserID = ta.AttendeeID AND st.SurveyID = ts.SurveyID))
--adding the piece such that we compare against the temp table...
AND (NOT EXISTS (SELECT * FROM #tSa tempS WHERE tempS.AttendeeID = ta.AttendeeID AND tempS.SurveyID = ts.SurveyID AND tempS.TrainingAttendeeID = ta.TrainingAttendeeID))
)
ORDER BY
ta.TrainingAttendeeID,
ta.AttendeeID,
ts.SurveyID
PRINT CAST('TrainingAttendeeID: ' + CAST(#TrainingAttendeeID as nvarchar(500)) + ' AttendeeID:' + CAST(#AttendeeID as nvarchar(500)) + ' SurveyID: ' + CAST(#SurveyID as nvarchar(500)) AS nvarchar(4000))
--insert into our temp table
INSERT INTO #tSa(AttendeeID, SurveyID, TrainingAttendeeID)
VALUES(#AttendeeID, #SurveyID, #TrainingAttendeeID)
END
END
GO
Variables will not change if select does not return any records. I bet it processes last #AttendeeID round and round.
Another way to test it - add unique constraint to temp table. I assume cycle will fail once there are no more records to select.
One way to fix it - assign NULLs to all variables at the beginning of each iteration (at the top of while body). But I'd recommend to rewrite this code to cursor if possible (not sure what is the logic of several select statements).
Note that declaration of variables within code block makes no "block-scope" sense since it is not perl or python.

Apply WHILE logic on Row-by-Row processing with Cursor

I have T-SQL script that is parsing the MDX expression. It looks as:
IF OBJECT_ID ( 'tempdb..#metrics' ) IS NOT NULL
DROP TABLE #metrics
CREATE TABLE #metrics (
Metric VARCHAR(255)
)
---
DECLARE #counter INT = 1
DECLARE #mdx VARCHAR(4000) = 'SELECT {[Measures].[One],[Measures].[Two],[Measures].[Three],[Measures].[Four]} DIMENSION, PROPERTIES OTHER'
DECLARE #startString INT
DECLARE #endString INT
DECLARE #metric VARCHAR(200)
WHILE (1=1)
BEGIN
-- loop data and process them
SET #startString = (SELECT PATINDEX('%[[]Measures%',#mdx))
SET #endString = (SELECT CHARINDEX(',',#mdx))
SET #metric = (SELECT SUBSTRING(#mdx, #startString, #endString - #startString))
IF #metric LIKE '%}%'
BEGIN
SET #metric = LEFT(#metric, CHARINDEX('}',#metric) - 1)
INSERT INTO #metrics ( Metric ) SELECT #metric
SET #mdx = REPLACE(#mdx, #metric, '')
END
ELSE
BEGIN
INSERT INTO #metrics ( Metric ) SELECT #metric
SET #metric = #metric + ','
SET #mdx = REPLACE(#mdx, #metric, '')
END
-- break while
IF #mdx NOT LIKE '%[[]Measures%,%'
BEGIN
BREAK;
END
END
---
SELECT * FROM #metrics
Now, I need to apply this on more rows, but did not figure out how. I tried it with cursor, but it never ends. How to loop the logic on the following rows?
DECLARE #srcTable TABLE (
ID INT
,textData VARCHAR(4000)
)
INSERT INTO #srcTable ( ID, textData ) ( 1, 'SELECT {[Measures].[One],[Measures].[Two],[Measures].[Three],[Measures].[Four]} DIMENSION, PROPERTIES OTHER' )
,(2, 'SELECT {[Measures].[Five],[Measures].[Six],[Measures].[Seven]} DIMENSION, PROPERTIES OTHER' )
Desired Result:
1 [Measures].[One]
1 [Measures].[Two]
1 [Measures].[Three]
1 [Measures].[Four]
2 [Measures].[Five]
2 [Measures].[Six]
2 [Measures].[Seven]
DECLARE #t TABLE (
ID INT,
Metric VARCHAR(255)
)
INSERT INTO #t
VALUES
(1, 'SELECT {[Measures].[One],[Measures].[Two],[Measures].[Three],[Measures].[Four]} DIMENSION, PROPERTIES OTHER'),
(2, 'SELECT {[Measures].[Five],[Measures].[Six],[Measures].[Seven]} DIMENSION, PROPERTIES OTHER')
SELECT r.ID, item = t.c.value('.', 'VARCHAR(255)')
FROM (
SELECT *, txml = CAST('<r>' + REPLACE(Metric, ',', '</r><r>') + '</r>' AS XML)
FROM (
SELECT ID, Metric = SUBSTRING(Metric, CHARINDEX('{',Metric) + 1, CHARINDEX('}',Metric) - CHARINDEX('{',Metric) - 1)
FROM #t
) t
) r
CROSS APPLY txml.nodes('/r') t(c)
Output -
ID item
----------- -----------------------
1 [Measures].[One]
1 [Measures].[Two]
1 [Measures].[Three]
1 [Measures].[Four]
2 [Measures].[Five]
2 [Measures].[Six]
2 [Measures].[Seven]

Select multiple columns but group by only one

Using SQL Server 2008. I have been researching this problem for days. Thought about CTE and trying to use a predicate on the problem tables.
Nothing I have tried or researched has worked so here I am. The problem is it's returning duplicate OrderID.
I've marked the problem joins.
Even tried OUTER APPLY but it caused certain searches not to work. Tried INNER APPLY then duplicates again.
The problem joins, the tables, have multiple references to OrderID.
So tblRun has multiple rows with the same OrderID showing which run it was in at and what date and so forth.
I really need suggestions from all the guru's out there.
Here is the SQL:
DECLARE #CompanyID INT = 22718,
#StartDate DATETIME = '',
#EndDate DATETIME = '',
#SalesRepID INT = NULL,
#AssignedTo INT = NULL,
#ServiceDefID INT = NULL,
#ProductName VARCHAR(512) = NULL,
#IsCCOrder BIT = NULL,
#OrderID INT = NULL,
#LocationID INT = NULL,
#SalesRepLocationID INT = NULL,
#PONum VARCHAR(150) = NULL,
#InvoiceID INT = NULL,
#IsSplitOrder BIT = NULL,
#ContactID INT = NULL,
#ContactName VARCHAR(150) = NULL,
#JobName VARCHAR(200) = NULL,
#Notes VARCHAR(MAX) = NULL,
#CompanyName VARCHAR(255) = NULL,
#DueDateFrom DATETIME = '',
#DueDateTo DATETIME = '',
#SubmitedDateFrom DATETIME = '',
#SubmitedDateTo DATETIME = '',
#IsRush BIT = NULL,
#Msg VARCHAR(1000) = NULL
--#Stages dbo.int_tbltype READONLY
DECLARE #Stages TABLE (ID INT)
--INSERT INTO #Stages (ID) VALUES (1)
DECLARE #DueDate DATETIME = NULL
SET NOCOUNT ON
DECLARE #OrderIDsTBL TABLE(OrderID INT)
IF #Msg IS NOT NULL
BEGIN
INSERT INTO #OrderIDsTBL (OrderID)
SELECT OrderID
FROM tblOrderLog
WHERE Msg LIKE '%' + #Msg + '%'
END
IF #OrderID IS NOT NULL
BEGIN
INSERT INTO #OrderIDsTBL (OrderID)
VALUES (#OrderID)
END
DECLARE #OderIDsCnt INT = (SELECT COUNT(OrderID) FROM #OrderIDsTBL)
DECLARE #StageCnt INT = (SELECT COUNT(ID) FROM #Stages)
SELECT
o.OrderID,
o.CompanyID,
co.Name AS CompanyName,
o.ContactID,
o.JobName,
p.FirstName + ' ' + p.LastName AS ContactName,
p2.FirstName + ' ' + p2.LastName AS SalesRep,
o.DueDate,
CASE WHEN MAX(oi.PriorityService) > 0 THEN 1 ELSE 0 END AS IsRush,
ISNULL(s.StageID, 0) AS StageID,
o.Notes, r.SubmittedComplete,
dbo.fOrderRunLocationCSVByOrderID(o.OrderID) AS LocationCSV,
(SELECT
STUFF((SELECT DISTINCT ' ' + st.Name + '<br />' FROM tblStage st
INNER JOIN tblOrderItem oi ON oi.OrderID = o.OrderID
INNER JOIN tblRun r ON r.OrderItemID = oi.OrderItemID
INNER JOIN tblStage s ON s.StageID = r.StageID
LEFT JOIN tblRunService rs ON rs.RunID = r.RunID
WHERE (s.StageID = st.StageID)
AND (rs.AssignedTo = #AssignedTo OR #AssignedTo IS NULL)
FOR XML PATH(''), TYPE).value('.','VARCHAR(max)'), 1, 1, ''))
AS Stages,
Row_Number() Over(Order By o.OrderID Desc) As RowNum
FROM
tblOrder o
INNER JOIN
tblCompany co ON co.CompanyID = o.CompanyID
INNER JOIN
tblParty p ON p.PartyID = o.ContactID
-------- PROBLEM JOINS ------------
LEFT JOIN
tblOrderItem oi ON oi.OrderID = o.OrderID
LEFT JOIN
tblRun r ON r.OrderItemID = oi.OrderItemID
LEFT JOIN
tblService srv ON srv.OrderItemID = oi.OrderItemID
-------- END PROBLEM JOINS ------------
LEFT JOIN
tblStage s ON s.StageID = r.StageID
LEFT JOIN
tblParty p2 ON p2.PartyID = o.SalesRepID
LEFT JOIN
tblEmployee e ON e.EmployeeID = o.SalesRepID
LEFT JOIN
tblShipTo st ON o.ShipToID = st.ShipToID
WHERE
(#CompanyID IS NULL OR (o.CompanyID = #CompanyID )) AND
(#IsCCOrder IS NULL OR (ISNULL(o.IsCreditCardOrder, 0) = #IsCCOrder )) AND
(#SalesRepID IS NULL OR o.SalesRepID = #SalesRepID) AND
(#ServiceDefID IS NULL OR (srv.ServiceDefID = #ServiceDefID)) AND
(#ProductName IS NULL OR (oi.Name LIKE '%' + #ProductName + '%')) AND
(#IsSplitOrder IS NULL OR (#IsSplitOrder = 1 AND oi.SplitOrderID IS NOT NULL)) AND
(
(#StartDate = '' OR #EndDate = '') OR
(#StartDate >= CreatedDate AND #EndDate <= COALESCE(CancelledDate, ClosedDate, GetDate())) OR
(#StartDate <= COALESCE(CancelledDate, ClosedDate, GETDATE()) AND #EndDate >= COALESCE(CancelledDate, ClosedDate, GetDate()) ) OR
(#StartDate <= CreatedDate AND #EndDate >= CreatedDate )
) AND
(#LocationID IS NULL OR (#LocationID = srv.LocationID OR srv.LocationID IS NULL)) AND
(#SalesRepLocationID IS NULL OR (#SalesRepLocationID = e.LocationID OR e.LocationID IS NULL))
AND (#InvoiceID IS NULL OR o.InvoiceID = #InvoiceID )
AND (#PONum IS NULL OR o.PONum LIKE '%' + #PONum + '%')
AND (COALESCE(s.StageID, 0) IN (SELECT ID FROM #Stages) OR #StageCnt = 0)
AND (o.ContactID = #ContactID OR #ContactID IS NULL)
AND (p.FirstName + ' ' + p.LastName LIKE '%' + #ContactName + '%' OR #ContactName IS NULL)
AND (o.JobName LIKE '%' + #JobName + '%' OR #JobName IS NULL)
AND (o.Notes LIKE '%' + #Notes + '%' OR #Notes IS NULL)
AND (co.Name LIKE '%' + #CompanyName + '%' OR #CompanyName IS NULL)
AND (o.DueDate >= #DueDateFrom OR #DueDateFrom = '')
AND (o.DueDate <= #DueDateTo OR #DueDateTo = '')
AND (r.SubmittedComplete >= #SubmitedDateFrom OR #SubmitedDateFrom = '')
AND (r.SubmittedComplete <= #SubmitedDateTo OR #SubmitedDateTo = '')
AND (#IsRush = (CASE WHEN oi.PriorityService > 0 THEN 1 ELSE 0 END)
OR #IsRush IS NULL)
AND (o.OrderID IN (SELECT OrderID FROM #OrderIDsTBL) OR #OderIDsCnt = 0)
GROUP BY
o.OrderID, o.CompanyID,
co.Name,
o.ContactID, o.JobName,
p.FirstName, p.LastName, p2.FirstName, p2.LastName,
o.DueDate, o.Notes,
r.SubmittedComplete,
s.StageID
Thanks for any suggestions. I've been working on this for some time now and just can't get it working right.
It looks like you're trying to do too much with a single SELECT statement. If you want one row per unique OrderID, then don't join with the tables that have multiple rows for the same OrderID. Remove the GROUP BY clause. Use one or more separate SELECT statements to get the details from the tables that have multiple rows per OrderID.
Thanks everyone for the suggestions but I found my own solution.
With the entire sql, I placed it into a temp table.
Then used this to sort out the duplicate OrderIds....
SELECT OrderID, CompanyID, ContactID, CompanyName, JobName, ContactName,
SalesRep, DueDate, IsRush , StageID, Notes, SubmittedComplete,
LocationCSV, Stages
FROM (SELECT *, ROW_NUMBER() OVER(PARTITION BY OrderID ORDER BY OrderID DESC) 'RowRank'
FROM #SearchTbl
)sub
WHERE RowRank = 1

Resources