Azure Cognitive Search: How to get collection of strings from a view - sql

I have an index definition on the Azure Cognitive Search and inside this index definition, there is a field called CustomerNames which of type collection (Collection(Edm.String)). Basically, this means my collection result will look like this: CustomerNames: ["Homer Simpson", "Henry Griffin", "Jane Doe"]
Here is the snapshot of the index definition:
Now I have a view that will act as a data source in this cognitive search and this view is:
CREATE VIEW [dbo].[vCog_CustomerActivityAttachmentSearchDocuments]
AS
SELECT
caa.Id,
caa.CustomerActivityId,
caa.AmsAttachmentId,
caa.OriginalFileName,
caa.[FileName],
caa.FileExtension,
caa.ContentType,
caa.[Description],
caa.DocumentTypeId,
caa.AdditionalInfo,
caa.Comments,
ca.CustomerId,
GuidCustomerId = ca.CustomerId,
CustomerNames =
(
SELECT
STRING_AGG(CONVERT(nvarchar(max),cp.FirstName + ' ' + cp.LastName), ', ')
FROM dbo.CustomerPersons AS cp with (nolock)
WHERE cp.CustomerId = c.Id AND cp.LegalEntityName IS NULL
),
CustomerPersons =
(
Select
cp.Id
, cp.CustomerId
, cp.NamePrefix
, cp.FirstName
, cp.MiddleName
, cp.LastName
, cp.DateOfBirth
, cp.HomePhone
, cp.WorkPhone
, cp.CellPhone
, cp.FaxPhone
, cp.Email
, cp.Email2
, cp.LegalEntityName
from
CustomerPersons cp with (nolock)
where
cp.CustomerId = c.Id FOR JSON AUTO
),
c.FirmName,
ca.PolicyId,
PolicyNumber = p.TrimmedPolicyNumber,
caa.CreatedAtUtc,
caa.[RowVersion]
FROM dbo.CustomerActivityAttachments caa with (nolock)
JOIN dbo.CustomerActivities ca with (nolock) on ca.Id = caa.CustomerActivityId
JOIN dbo.Customers c with (nolock) on c.Id = ca.CustomerId
LEFT JOIN dbo.Policies p with (nolock) on p.Id = ca.PolicyId
where IsNull(caa.UpdatedAtUtc, caa.CreatedAtUtc) > GetDate() - 1200
GO
So when I run the indexer on the cognitive search, it is unable to recognize the CustomerNames and throwing the following error:
The data field 'CustomerNames' in the document with key 'XXXXXXXX' has an invalid value of type 'Edm.String' (String maps to Edm.String). The expected type was 'Collection(Edm.String)'.
So my question is how do I change my query in a way that I am getting a JSON array of strings and making it recognizable by the search function?
What I have tried so far: I have tried using this query inside the customerNames:
SELECT
JSON_QUERY('[' + STUFF(( SELECT ',' + '"' + STRING_AGG(CONVERT(nvarchar(max),cp.FirstName + ' ' + cp.LastName), ', ') + '"'
FROM dbo.CustomerPersons AS cp with (nolock)
WHERE cp.CustomerId = c.Id AND cp.LegalEntityName IS NULL
FOR XML PATH('')),1,1,'') + ']') as [CustomerNames]
FOR JSON PATH , WITHOUT_ARRAY_WRAPPER
But this is not solving the problem. Any ideas will be greatly appreciated. Thanks in advance.

you can use Field mapping function - jsonArrayToStringCollection to convert the json array to Index collection
So let your query generate a column with name CustomerNamesJArray and map it to CustomerNames and have a jsonArrayToStringCollection mapping function.
https://learn.microsoft.com/en-us/azure/search/search-indexer-field-mappings#field-mapping-functions

Related

SSRS Subreport runs multiple times, I only want it running once

I have a report that has a drillthrough subreport that runs multiple times when it has more than one relationship to a many to many item that has nothing to do with the subreport.
Main report query
SELECT DISTINCT
cat.CategoryName AS 'Category Name', sub.SubCategoryName AS 'SubCategory Name', cur.Status, cur.PastConsiderationFlag, cur.Model, cur.Version, cur.Vendor, cur.AvailableDate AS 'Available Date', cur.EndOfProduction AS 'End of Production',
cur.EndOfSupport AS 'End of Support', dep.DepartmentName AS 'Department Name', emp.FirstName + ' ' + emp.LastName AS 'Tech Owner', emp2.FirstName + ' ' + emp2.LastName AS 'Tech Contact',
cur.NumOfDevices AS '# of Devices', cur.UpgradeDuration AS 'Upgrade Duration', cur.FiscalConsideration AS 'Fiscal Consideration', cur.Description, cur.SupportingComments, cur.CurrencyId, STUFF
((SELECT ', ' + pl.PlatformName AS Expr1
FROM Platform AS pl LEFT OUTER JOIN
Currency_Platform AS cp ON cur.CurrencyId = cp.CurrencyId
WHERE (pl.PlatformId = cp.PlatformId) FOR XML PATH('')), 1, 1, '') AS 'Platforms', ISNULL(STUFF
((SELECT ', ' + cu2.Model AS Expr1
FROM Currency AS cu2 RIGHT OUTER JOIN
Currency_Dependency AS cd ON cur.CurrencyId = cd.CurrencyId
WHERE (cu2.CurrencyId = cd.DependencyId) FOR XML PATH('')), 1, 1, ''), 'N/A') AS 'Dependencies', ISNULL(STUFF
((SELECT ', ' + cu2.Model AS Expr1
FROM Currency AS cu2 RIGHT OUTER JOIN
Currency_Affected AS ca ON cur.CurrencyId = ca.CurrencyId
WHERE (cu2.CurrencyId = ca.AffectedId) FOR XML PATH('')), 1, 1, ''), 'N/A') AS 'Affected Apps', Currency_Platform.PlatformId
FROM Currency AS cur INNER JOIN
SubCategory AS sub ON cur.SubCategoryId = sub.SubCategoryId INNER JOIN
Category AS cat ON sub.CategoryId = cat.CategoryId LEFT OUTER JOIN
Employee AS emp ON cur.OwnerId = emp.EmployeeId LEFT OUTER JOIN
Employee AS emp2 ON cur.ContactId = emp2.EmployeeId LEFT OUTER JOIN
Department AS dep ON cur.PortfolioOwnerId = dep.DepartmentId LEFT OUTER JOIN
Currency_Platform ON cur.CurrencyId = Currency_Platform.CurrencyId
Even though it's a distinct select, the subreport will run equal to the amount of Platforms it belongs to. I'll include the Query for the subreport here.
;with cte as (
-- anchor elements: where curr.Status = 1 and not a dependent
select
CurrencyId
, Model
, Version
, ParentId = null
, ParentModel = convert(varchar(128),'')
, Root = curr.Model
, [Level] = convert(int,0)
, [ParentPath] = convert(varchar(512),Model + Version)
from dbo.Currency as curr
where curr.Status = 1
/* anchor's do not depend on any other currency */
and not exists (
select 1
from dbo.Currency_Dependency i
where curr.CurrencyId = i.DependencyId
)
-- recursion begins here
union all
select
CurrencyId = c.CurrencyId
, Model = c.Model
, Version = c.Version
, ParentId = p.CurrencyId
, ParentModel = convert(varchar(128),p.Model + p.Version)
, Root = p.Root
, [Level] = p.[Level] + 1
, [ParentPath] = convert(varchar(512),p.[ParentPath] + ' > ' + c.Model + ' ' + c.Version)
from dbo.Currency as c
inner join dbo.Currency_Dependency as dep
on c.CurrencyId = dep.DependencyId
inner join cte as p
on dep.CurrencyId = p.CurrencyId
)
select CurrencyId, ParentPath, Model + ' ' + Version AS 'Model' from cte
WHERE CurrencyId = #CurrencyId
When I run the subreport individually, everything is fine. When I open the subreport through the main report passing the CurrencyId as a parameter, it does so as many times as the amount of platforms it belongs to.
Is there a way I can correct this either by improving the queries, or as I would prefer, force the subreport to only run once no matter what?
Thanks so much for having a look.
You can use SQL Server Profiler to check the following things.
How many times and with what parameters is the subreport query has ran
How many values your first query returned
I don't think your problem is more about SSRS than it is about your T-SQL Code. I'm going to guess and say that the subreport object is in the report detail section of the report. That means that the subreport is going to render once for every row in the main queries dataset. I don't have any idea what your container report actually looks like but one option you have might be to include the subreport in the header or footer section and have it run off of a MAX(), MIN(), of a value that you know will be the same for every row.

Create View with 'STUFF' function - conversion failed nvarchar to data type int

I am confused I created a view that uses the STUFF function on an int. It was working however I had to drop my table and reload it and now my view is not working. I receive the following error Conversion failed when converting the nvarchar value ' 5, 4' to data type int.. I am loading the table from the same insert script that I used last time with the addition of one field which shouldn't have an affect. My create view script is as follows:
CREATE VIEW [AQB_OB].[GISREQUESTEDBURNS]
AS
with conditions as
(SELECT DISTINCT BD.[RequestedBurnsID]
,[ConditionsReasonsID] = STUFF((SELECT ', ' + CONVERT(VARCHAR(20),[ConditionsReasonsID]) FROM [AQB_OB].[BurnDecisions] WHERE [RequestedBurnsID]= BD.[RequestedBurnsID] ORDER BY [RequestedBurnsID] ASC
FOR XML PATH ('')) , 1 , 1, '') FROM
[AQB_OB].[BurnDecisions] BD)
SELECT RB.[RequestedBurnsID] AS REQUESTEDBURNID
,BUY.[BurnYear] AS BURNYEAR
,CY.[CurrentYear] AS CURRENTYEAR
,RB.[BurnSitesID] AS BURNSITESID
,[BurnerID] AS BURNERID
,[Contact] AS CONTACT
,[Latitude] AS LATITUDE
,[Longitude] AS LONGITUDE
,[BurnStartDate] AS BURNSTARTDATE
,[BurnEndDate] AS BURNENDDATE
,RB.[NumberPiles] AS NUMBERPILES
,[BurnDecision] AS BURNDECISION
,RB.[Comment] AS COMMENT
,CC.ConditionsReasonsID AS CONDITIONS
FROM [AQB_MON].[AQB_OB].[RequestedBurns] RB
inner join AQB_MON.[AQB_OB].[BurnSites] BS on RB.BurnSitesID = BS.BurnSitesID
inner join AQB_MON.[AQB_OB].[Contacts] CT on RB.ContactsID = CT.ContactsID
inner join AQB_MON.[AQB_OB].[BurnProject] BP on BP.BurnProjectID = BS.BurnProjectID
inner join AQB_MON.[AQB_OB].[BurnYears] BUY on BUY.BurnYearID = BP.BurnYearID
inner join AQB_MON.[AQB_OB].[CurrentYear] CY on CY.CurrentYearID = BUY.CurrentYearID
full outer join conditions CC on CC.RequestedBurnsID = RB.RequestedBurnsID
INNER JOIN [AQB_OB].[ConditionsReasons] CR ON CR.ConditionsReasonsID = CC.ConditionsReasonsID
GO

SQL server Stuff on multiple columns

I want to concatenate the value of multiple columns for the same ID.
I managed to concatenate for the first column, but when trying the same syntax for the second I'm having an error "The multi-part identifier EnqAct.[ActionID] could not be bound."
Example_Data_Result
Here I managed to group several MachineName together, as seen in "Column1" but I can't manage to group both the MachineName and Description in their own column
My working Query :
SELECT Enq.[EnquiryID],
Enq.[CustomerName],
DetPrio.[Description],
Stuff((SELECT ', ' + Mach.[MachineName]
FROM [dbo].[Machine] Mach
INNER JOIN [dbo].[MachineEnquiry] MachEnq
ON Mach.[MachineID] = MachEnq.[MachineID]
WHERE Enq.[EnquiryID] = MachEnq.[EnquiryID]
FOR XML PATH('')), 1, 2, ''),
DetAct.[Description]
FROM [dbo].[Enquiry] Enq
INNER JOIN [dbo].[EnquiryAction] EnqAct
ON EnqAct.[EnquiryID] = Enq.[EnquiryID]
INNER JOIN [dbo].[DetailsAction] DetAct
ON DetAct.[ActionID] = EnqAct.[ActionID]
INNER JOIN [dbo].[DetailsPriority] DetPrio
ON DetPrio.[PriorityID] = Enq.[Priority]
GROUP BY Enq.[EnquiryID],
Enq.[CustomerName],
DetPrio.[Description],
DetAct.[Description]
My non working Query :
SELECT Enq.[EnquiryID],
Enq.[CustomerName],
DetPrio.[Description],
Stuff((SELECT ', ' + Mach.[MachineName]
FROM [dbo].[Machine] Mach
INNER JOIN [dbo].[MachineEnquiry] MachEnq
ON Mach.[MachineID] = MachEnq.[MachineID]
WHERE Enq.[EnquiryID] = MachEnq.[EnquiryID]
FOR XML PATH('')), 1, 2, ''),
Stuff((SELECT ', ' + DetAct.[Description]
FROM [dbo].[DetailsAction] DetAct
INNER JOIN [dbo].[EnquiryAction] EnqAct
ON EnqAct.[ActionID] = DetAtc.[ActionID]
WHERE Enq.[EnquiryID] = EnqAct.[EnquiryID]
FOR XML PATH('')), 1, 2, '')
FROM [dbo].[Enquiry] Enq
INNER JOIN [dbo].[DetailsPriority] DetPrio
ON DetPrio.[PriorityID] = Enq.[Priority]
GROUP BY Enq.[EnquiryID],
Enq.[CustomerName],
DetPrio.[Description]
Both work the same way, I have a table Enquiry which will have an EnquiryID.
then in my table EnquiryAction or MachineEnquiry I will have entitys with an EnquiryID and an Action/Machine ID
Then in my DetailsAction/Machine Table I will have the Action/Machine ID, and the string I want to get and concatenate.
Why am I having an error and is it possible to achieve what I'm trying to do ?

What Is Wrong With This FOR XML PATH

I can't seem to figure out why this won't work in MS SQL Server. It seems to not group the lines. Specifically I see:
1036 SC
1036 S1
1094 VO
1094 V1
1094 V2
When I expect to see:
1036 SC,S1
1094 VO,V1,V2
Can someone see something wrong with the syntax?
SELECT DISTINCT oa.acct_cd AS [Account],
STUFF((SELECT ',' + CASE WHEN o.trans_type like 'BUY%' then 'buy of ' else 'sell of ' end + s.ticker AS [text()]
FROM [dbo].[synCRtblTS_ORDER] o INNER JOIN [dbo].[synCRtblCSM_SECURITY] s
ON o.SEC_ID = s.SEC_ID
WHERE o.ORDER_ID = oa.ORDER_ID AND o.status IN ('OPEN','WORK','PENDING')
FOR XML PATH('')), 1, 1, '') [buy/sell]
FROM [dbo].[synCRtblTS_ORDER_ALLOC] oa INNER JOIN tblPortfolio p
ON oa.ACCT_CD = p.Account INNER JOIN tblInvestmentObjective io
ON io.Code = p.InvestmentObjective
WHERE p.AsOfDate = (SELECT AsOfDate FROM tblDateAsOf) and io.CashMgmtStrategy IN ('SC','VO')
GROUP BY oa.ORDER_ID, oa.acct_cd
order by 1
The Information you give is not enough... Within your STUFF you create (and concatenate) string which should contain "buy of" or "sell of". You are missing this information in your output.
It's guessing that your SC, S1, VO values are CashMgmtStrategy entries. You are not concatenating them...
Without deeper knowledge of your tables I cannot solve your problem, but here you'll find a working example of concatenation via FOR XML and STUFF
This code will list all table's names and their columns in a comma delimited list.
SELECT DISTINCT tbls.name AS TableName,
STUFF(
(
SELECT ', ' + cols.name
FROM sys.columns AS cols
WHERE cols.object_id = tbls.object_id
FOR XML PATH('')
), 1, 2, '') AS ColumnList
FROM sys.tables AS tbls

Parsing error when creating view

I have a view which takes multiple rows and Comma Separated Values (CSV) from table columns with data.
It was working well and I got the results that I needed. Now the view has some parsing error like:
Error in WHERE clause near '('. Unable to parse query text.
Can someone help? Here is my code:
SELECT dbo.table1.title,
Stuff((SELECT ', ' + CONVERT(NVARCHAR(4000), dbo.table3.uid) AS [text()]
FROM dbo.table2
INNER JOIN dbo.table3
ON dbo.table3.uid = dbo.table2.FK_Group
WHERE dbo.table3.uid = dbo.table2.FK_Group
AND dbo.table3.company = dbo.main.company
AND dbo.table2.FK_Version = dbo.table1.fk_Version
AND dbo.main_version.uid = dbo.table1.fk_Version
FOR XML PATH('')), 1, 1, '') AS groupName
FROM dbo.main_version
INNER JOIN dbo.[main]
ON dbo.version.fk_main = dbo.[main].uid
INNER JOIN dbo.main_schema
ON dbo.[main].fk_SCHEMA = dbo.main_schema.uid
INNER JOIN dbo.table1
ON dbo.version.uid = dbo.table1.fk_Version
WHERE ( dbo.main_version.active = 1 )