Not able to create UNIQUE CLUSTERED INDEX on View WITH SCHEMABINDING having sub queries - sql-server-2012

Below is the code:
CREATE VIEW [dbo].[View_GetAllContents] WITH SCHEMABINDING AS
SELECT C.ContentID,
C.Title,
C.[Description],
C.Tags,
C.Markets,
C.Formats,
C.Categories,
C.IsGlobalSalesResource,
C.IsActive,
C.CreatedBy,
C.CreatedDate,
C.ModifiedBy,
STUFF(
(SELECT ',' + T.TagName
FROM [dbo].[Tags] T
WHERE T.IsActive=1
AND T.TagID IN
(SELECT LTRIM(RTRIM(items))
FROM [dbo].[SplitString](C.Tags, ','))
FOR XML PATH(''), TYPE).value('.[1]', 'nvarchar(max)'), 1, 2, '') AS TagNames,
STUFF(
(SELECT ',' + M.MarketName
FROM [dbo].[Markets] M
WHERE M.IsActive=1
AND M.MarketID IN
(SELECT LTRIM(RTRIM(items))
FROM [dbo].[SplitString](C.Markets, ','))
FOR XML PATH(''), TYPE).value('.[1]', 'nvarchar(max)'), 1, 2, '') AS MarketNames,
STUFF(
(SELECT ',' + F.FormatName
FROM [dbo].[Formats] F
WHERE F.IsActive=1
AND F.FormatID IN
(SELECT LTRIM(RTRIM(items))
FROM [dbo].[SplitString](C.Formats, ','))
FOR XML PATH(''), TYPE).value('.[1]', 'nvarchar(max)'), 1, 2, '') AS FormatNames,
STUFF(
(SELECT ',' + Ca.CategoryName
FROM [dbo].[Categories] Ca
WHERE Ca.IsActive=1
AND Ca.CategoryID IN
(SELECT LTRIM(RTRIM(items))
FROM [dbo].[SplitString](C.Categories, ','))
FOR XML PATH(''), TYPE).value('.[1]', 'nvarchar(max)'), 1, 2, '') AS CategorieNames,
STUFF(
(SELECT '$A$' + cast(A.AttachmentID AS varchar) + '$,$' + cast(A.ActualFileName AS nvarchar(1000))
FROM [dbo].[Attachments] A
WHERE A.ContentID=C.ContentID
FOR XML PATH(''), TYPE).value('.[1]', 'nvarchar(max)'), 1, 3, '') AS Attachments
FROM [dbo].[Contents] C GO
Error on below code:
CREATE UNIQUE CLUSTERED INDEX [IX_View_GetAllContents_ContentID] ON [dbo].[View_GetAllContents](ContentID);
GO
Exception:
Cannot create index on view "SM_SalesWarehouse.dbo.View_GetAllContents" because it contains one or more subqueries. Consider changing the view to use only joins instead of subqueries. Alternatively, consider not indexing this view.

Related

how to insert a line break after every second loop in t-sql stuff function

how can i insert a CHAR(10) after every second loop in t-sql stuff function in my query
SELECT STUFF(
(
SELECT ', ' + new_name
FROM new_subcatagories
FOR XML PATH(''), TYPE
).value('.', 'VARCHAR(MAX)'), 1, 2, '')
so the result should by
record1,record2,
record3,record4
You could use a CASE expression to see if the value of ROW_NUMBER is divisible by 2, and if not then add a carriage return and line break:
SELECT STUFF((SELECT CASE WHEN ROW_NUMBER() OVER (order by new_nam) % 2 = 1 THEN CHAR(13) + CHAR(10) ELSE '' END + ', ' + new_nam
FROM new_subcatagories
ORDER BY new_nam
FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'), 1, 4, '');

Xml Column Into Multiple Column With Separated Comma In Sql Server

Using Sql Server 2012
I have table with single field within String containing xml format like below,
a
----
<data1>11</data1><data2>4</data2><data1>12</data1><data2>5</data2>
I want result table with containing separate comma for each column like this
data1|data2
-----------
11,12|4,5
Here's your script. Your a column is not a valid XML type, so i need to append as root element.
declare #strxml xml = concat('<t>', '<data1>11</data1><data2>4</data2><data1>12</data1><data2>5</data2>', '</t>')
SELECT
STUFF((SELECT ',' + b.dat.value('.', 'NVARCHAR(MAX)')
FROM tmp.node.nodes('data1') b (dat)
FOR XML PATH(''),TYPE).value('.', 'NVARCHAR(MAX)'),
1, 1, '') AS a,
STUFF((SELECT ',' + a.dat.value('.', 'NVARCHAR(MAX)')
FROM tmp.node.nodes('data2') a (dat)
FOR XML PATH(''),TYPE).value('.', 'NVARCHAR(MAX)'),
1, 1, '') AS b
FROM #strxml.nodes('/t') tmp(node);
applying your table. just replace test3 and yourcolumn
SELECT
STUFF((SELECT ',' + b.dat.value('.', 'NVARCHAR(MAX)')
FROM tmp.node.nodes('data1') b (dat)
FOR XML PATH(''),TYPE).value('.', 'NVARCHAR(MAX)'),
1, 1, '') AS a,
STUFF((SELECT ',' + a.dat.value('.', 'NVARCHAR(MAX)')
FROM tmp.node.nodes('data2') a ( dat )
FOR XML PATH(''),TYPE).value('.', 'NVARCHAR(MAX)'),
1, 1, '') AS b
FROM test3 t
CROSS APPLY (select cast(concat('<t>', yourcolumn, '</t>') AS xml)) as t1(X)
CROSS APPLY t1.X.nodes('t') AS tmp(node)
DECLARE #XMLData XML
SET #XMLData = '<a>
<data1>11</data1><data2>4</data2><data1>12</data1><data2>5</data2>
</a>'
SELECT REPLACE
(
#XMLData.query('data(a/data1)').value('.','varchar(100)')
,' ' -- replace the white spaces
,',' -- replace the white spaces with commas
) AS data1,
REPLACE
(
#XMLData.query('data(a/data2)').value('.','varchar(100)')
,' '
,','
) AS data2
OR
If you don't have any Root
DECLARE #XMLData XML
SET #XMLData = '
<data1>11</data1><data2>4</data2><data1>12</data1><data2>5</data2>
'
SELECT REPLACE
(
#XMLData.query('data(data1)').value('.','varchar(100)')
,' ' -- replace the white spaces
,',' -- replace the white spaces with commas
) AS data1,
REPLACE
(
#XMLData.query('data(data2)').value('.','varchar(100)')
,' '
,','
) AS data2
Note:-
1. First we have space separated value...
2. To fulfill our objective we can use Replace function to replace the spaces with comma's.

Get unique values from multiple columns in single request

I have an employee data with several columns. I have a WebAPI that is reading from this database for a search application that surfaces users. I need to get a list of unique values for 4 of the fields. I am hoping to do this in a single query if possible.
I have 25+ columns but I need the unique values for 4 columns (JobTitle,Department,Position,Group). I just need them return as a comma-separated list.
Sample SQL Server 2016 Table:
Name | JobTitle | Department | Position | Group
------|----------|--------------|------------|---------
John | Partner | Department1 | Position1 | Group1
Jane | Manager | Department2 | Position2 | Group2
Joe | Analyst | Department2 | Position2 | Group2
I want my results to be a single row with a list of unique value that are comma-separated:
Single row returned
Departments: Department1,Department2
JobTitles: Partner,Manager,Analyst
Positions: Position1,Position2
Groups: Group1, Group2
Upto SQL Server 2016, you can use STUFF to concatenate STRING from different row into one Row/Column with a comma separator. This following script will return list of DISTINCT values as per your requirement-
SELECT DISTINCT
STUFF((SELECT DISTINCT ',' + A.JobTitle FROM Employee A FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') JobTitle,
STUFF((SELECT DISTINCT ',' + A.Department FROM Employee A FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') Department,
STUFF((SELECT DISTINCT ',' + A.Position FROM Employee A FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') Position,
STUFF((SELECT DISTINCT ',' + A.[Group] FROM Employee A FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') [Group]
FROM Employee A
If you want to add label before the list of distinct values, use this following script-
SELECT
'JobTitles: ' + B.JobTitle AS JobTitle,
'Departments: ' + B.Department AS Department,
'Positions: ' + B.Position AS Position,
'Groups: ' + B.[Group] AS [Group]
FROM
(
SELECT DISTINCT
STUFF((SELECT DISTINCT ',' + A.JobTitle FROM Employee A FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') JobTitle,
STUFF((SELECT DISTINCT ',' + A.Department FROM Employee A FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') Department,
STUFF((SELECT DISTINCT ',' + A.Position FROM Employee A FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') Position,
STUFF((SELECT DISTINCT ',' + A.[Group] FROM Employee A FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '') [Group]
FROM Employee A
)B

Stuff query in SQL Server

SELECT DISTINCT
AcNumber,
(SELECT STUFF((SELECT '::' + (REPLACE(RTRIM(LTRIM([master].dbo.Mig_fn_cutString([master].dbo.Mig_fn_StringReduce(UPPER(NomiName)),35,',',1,'Y','F'))),',',' '))
FROM [DepNominee] DPN
WHERE (AcNumber = DPN.AcNumber)
FOR XML PATH(''), TYPE).value('(./text())[1]', 'VARCHAR(MAX)'), 1, 2, '')) AS JBL_NOM_NAME,
(SELECT STUFF((SELECT '::' + (REPLACE(RTRIM(LTRIM([master].dbo.Mig_fn_cutString([master].dbo.Mig_fn_StringReduce(UPPER(FHName)),35,',',1,'Y','F'))),',',' '))
FROM [DepNominee] DPN
WHERE (AcNumber = DPN.AcNumber)
FOR XML PATH(''),TYPE).value('(./text())[1]', 'VARCHAR(MAX)'), 1, 2, '')) AS NOM_FATH_NAME,
(SELECT STUFF((SELECT '::' + (REPLACE(RTRIM(LTRIM([master].dbo.Mig_fn_cutString([master].dbo.Mig_fn_StringReduce(UPPER(MHName)),35,',',1,'Y','F'))),',',' '))
FROM [DepNominee] DPN
--WHERE (AcNumber = DPN.AcNumber)
FOR XML PATH(''),TYPE).value('(./text())[1]', 'VARCHAR(MAX)'), 1, 2, '')) AS NOM_MOTH_NAME
FROM
[DepNominee] DPN
GROUP BY
AcNumber, NomiName
That is my code, I want to see all data according my AccountNumber. But I see only one data repeating all the time in different account number. I attach the image:
I suspect the problem is that you are using the alias DPN in more than one place, causing your subqueries not to be correlated.
Try it like this:
SELECT DISTINCT
AcNumber,
(SELECT STUFF((SELECT '::' + (REPLACE(RTRIM(LTRIM([master].dbo.Mig_fn_cutString([master].dbo.Mig_fn_StringReduce(UPPER(NomiName)),35,',',1,'Y','F'))),',',' '))
FROM [DepNominee] DPN2
WHERE (DPN.AcNumber = DPN2.AcNumber)
FOR XML PATH(''), TYPE).value('(./text())[1]', 'VARCHAR(MAX)'), 1, 2, '')) AS JBL_NOM_NAME,
(SELECT STUFF((SELECT '::' + (REPLACE(RTRIM(LTRIM([master].dbo.Mig_fn_cutString([master].dbo.Mig_fn_StringReduce(UPPER(FHName)),35,',',1,'Y','F'))),',',' '))
FROM [DepNominee] DPN2
WHERE (DPN.AcNumber = DPN2.AcNumber)
FOR XML PATH(''),TYPE).value('(./text())[1]', 'VARCHAR(MAX)'), 1, 2, '')) AS NOM_FATH_NAME,
(SELECT STUFF((SELECT '::' + (REPLACE(RTRIM(LTRIM([master].dbo.Mig_fn_cutString([master].dbo.Mig_fn_StringReduce(UPPER(MHName)),35,',',1,'Y','F'))),',',' '))
FROM [DepNominee] DPN2
--WHERE (DPN.AcNumber = DPN2.AcNumber)
FOR XML PATH(''),TYPE).value('(./text())[1]', 'VARCHAR(MAX)'), 1, 2, '')) AS NOM_MOTH_NAME
FROM
[DepNominee] DPN
GROUP BY
AcNumber, NomiName

Select comma sperated column value

I'm trying to get comma , separated column value in SQL Server.
Select
CT.ClaimTypeId, CT.ClaimTypeName,CT.MHWSchemeNo,CT.MHWClaimTypeID,CFCTR.FormId,CF.Name,
FF.FormId,FF.FieldId,FF.Label,FF.Name,FF.IsDefaultField,FF.IsFieldLabelVisible,FF.IsRequired,FF.Type,
Label = STUFF((
SELECT ',' +JFFO.Label
FROM dbo.FormFieldOption JFFO
where JFFO.FieldId = FF.FieldId
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, ''),
Value= STUFF((
SELECT ',' +JFFO.Value
FROM dbo.FormFieldOption JFFO
where JFFO.FieldId = FF.FieldId
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, ''),
AdditionalTextfieldName= STUFF((
SELECT ',' +JFFO.AdditionalTextfieldName
FROM dbo.FormFieldOption JFFO
where JFFO.FieldId = FF.FieldId
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
from EmployeeClaimTypeRelationship ECR
LEFT JOIN ClaimType CT on CT.MHWSchemeNo=ECR.MHWSchemeNo
LEFT JOIN ClaimFormClaimTypeRelationship CFCTR on CFCTR.ClaimTypeId=CT.ClaimTypeId
LEFT JOIN ClaimForm CF on CF.FormId=CFCTR.FormId
LEFT JOIN FormField FF on FF.FormId=CFCTR.FormId
LEFT JOIN FormFieldOption FFO on FFO.FieldId=FF.FieldId
where ECR.MHWUserId='CITITEST1'
group by FF.FieldId,CT.ClaimTypeId, CT.ClaimTypeName,CT.MHWSchemeNo,CT.MHWClaimTypeID,CFCTR.FormId,CF.Name,
FF.FormId,FF.FieldId,FF.Label,FF.Name,FF.IsDefaultField,FF.IsFieldLabelVisible,FF.IsRequired,FF.Type
This is my query. And it is giving me the correct result. Here I'm using group by clause.
Now I want to optimize this query.
As you can see above, I have 3 columns which have comma , separated values which are coming from same table.
Is there any way so that I don't have to write multiple time same query for different fields?
Like this
Select
CT.ClaimTypeId, CT.ClaimTypeName,CT.MHWSchemeNo,CT.MHWClaimTypeID,CFCTR.FormId,CF.Name,
FF.FormId,FF.FieldId,FF.Label,FF.Name,FF.IsDefaultField,FF.IsFieldLabelVisible,FF.IsRequired,FF.Type,
Label = STUFF((
SELECT ',' +JFFO.Label
FROM dbo.FormFieldOption JFFO
where JFFO.FieldId = FF.FieldId
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, ''),
Value,AdditionalTextfieldName = STUFF((
SELECT ',' +JFFO.Value as Value,','+JFFO.AdditionalTextfieldName as AdditionalTextfieldName
FROM dbo.FormFieldOption JFFO
where JFFO.FieldId = FF.FieldId
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
from EmployeeClaimTypeRelationship ECR
LEFT JOIN ClaimType CT on CT.MHWSchemeNo=ECR.MHWSchemeNo
LEFT JOIN ClaimFormClaimTypeRelationship CFCTR on CFCTR.ClaimTypeId=CT.ClaimTypeId
LEFT JOIN ClaimForm CF on CF.FormId=CFCTR.FormId
LEFT JOIN FormField FF on FF.FormId=CFCTR.FormId
LEFT JOIN FormFieldOption FFO on FFO.FieldId=FF.FieldId
where ECR.MHWUserId='CITITEST1'
group by FF.FieldId,CT.ClaimTypeId, CT.ClaimTypeName,CT.MHWSchemeNo,CT.MHWClaimTypeID,CFCTR.FormId,CF.Name,
FF.FormId,FF.FieldId,FF.Label,FF.Name,FF.IsDefaultField,FF.IsFieldLabelVisible,FF.IsRequired,FF.Type
You could have a view.
CREATE VIEW view_name AS
SELECT * FROM ... WHERE ...
(Instead of *, you might prefer to select the union of all columns you ever might need and possibly give them aliases.) Then you would only need to
SELECT column1, column2, column3
FROM view_name
WHERE [additional conditions]
I would create a UDF Table-Valued Function and call that, it will also give you some performance benefit
Function Definition
CREATE FUNCTION dbo.fn_FormFieldOptionList ( #FieldId INT)
RETURNS TABLE
AS
RETURN (
SELECT DISTINCT
Label = STUFF((
SELECT ',' +JFFO.Label
FROM dbo.FormFieldOption JFFO
where JFFO.FieldId = FF.FieldId
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
,Value= STUFF((
SELECT ',' +JFFO.Value
FROM dbo.FormFieldOption JFFO
where JFFO.FieldId = FF.FieldId
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
,AdditionalTextfieldName= STUFF((
SELECT ',' +JFFO.AdditionalTextfieldName
FROM dbo.FormFieldOption JFFO
where JFFO.FieldId = FF.FieldId
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
FROM dbo.FormFieldOption FF
WHERE FF.FieldId = #FieldId )
Your Query
Select
CT.ClaimTypeId, CT.ClaimTypeName,CT.MHWSchemeNo
,CT.MHWClaimTypeID,CFCTR.FormId,CF.Name
,FF.FormId,FF.FieldId,FF.Label,FF.Name
,FF.IsDefaultField,FF.IsFieldLabelVisible
,FF.IsRequired,FF.Type,f.Label. f.Value ,f.AdditionalTextfieldName
from EmployeeClaimTypeRelationship ECR
LEFT JOIN ClaimType CT on CT.MHWSchemeNo=ECR.MHWSchemeNo
LEFT JOIN ClaimFormClaimTypeRelationship CFCTR on CFCTR.ClaimTypeId=CT.ClaimTypeId
LEFT JOIN ClaimForm CF on CF.FormId=CFCTR.FormId
LEFT JOIN FormField FF on FF.FormId=CFCTR.FormId
OUTER APPLY dbo.fn_FormFieldOptionList(FF.FieldId) f
where ECR.MHWUserId='CITITEST1'
Here in this query, we are joining dbo.FormFieldOption twice. Good optimization & speed can be achieved if we can restructure the query. Try to restructure the join
towards table dbo.FormFieldOption to single.