Approving "One" in a one-to-many DB relationship only when ALL "Many"s are approved - sql

I've tried looking for this I promise, but its kind of a hard question to search for...
I have a database with two tables linked in a one-to-many relationship where each "one" is an invoice header linked to "many" invoice lines.
I am designing a tool that will match each invoice line to a purchase order and I want to be able to mark an invoice header as "matched" only when all lines have been matched.
Does anyone know how to write this update query?

The relational operator you seek is known formally as division and colloquially as "the suppliers who supply all parts". For various reasons, a division operator has not appeared in any SQL product I know of, Access included. Instead, you need to use other operators in combination to do the same. See Divided we stand: the SQL of relational division by Joe Celko.

An approach available to users of Access 2010 and later is to use event-driven data macros in the child table to maintain the status flag in the parent table. For example, with a parent table
[InvHeader]
InvID AllMatched
----- ----------
1 No
and a child table
[InvItem]
ItemID InvID Matched
------ ----- -------
1 1 Yes
2 1 No
the following After Update data macro will automatically update the corresponding row in [InvHeader] after a child row has been changed in [InvItem]
Code:
<?xml version="1.0" encoding="UTF-16" standalone="no"?>
<DataMacros xmlns="http://schemas.microsoft.com/office/accessservices/2009/11/application">
<DataMacro Event="AfterUpdate">
<Statements>
<Action Collapsed="true" Name="SetLocalVar">
<Argument Name="Name">newAllMatched</Argument>
<Argument Name="Value">True</Argument>
</Action>
<ForEachRecord>
<Data Alias="i">
<Reference>InvItem</Reference>
<WhereCondition>[i].[InvID]=[InvItem].[InvID]</WhereCondition>
</Data>
<Statements>
<ConditionalBlock>
<If>
<Condition>Not [i].[Matched]</Condition>
<Statements>
<Action Collapsed="true" Name="SetLocalVar">
<Argument Name="Name">newAllMatched</Argument>
<Argument Name="Value">False</Argument>
</Action>
<Action Name="ExitForEachRecord"/>
</Statements>
</If>
</ConditionalBlock>
</Statements>
</ForEachRecord>
<LookUpRecord>
<Data Alias="hdr">
<Reference>InvHeader</Reference>
<WhereCondition>[hdr].[InvID]=[InvItem].[InvID]</WhereCondition>
</Data>
<Statements>
<ConditionalBlock>
<If>
<Condition>[hdr].[AllMatched]<>[newAllMatched]</Condition>
<Statements>
<EditRecord>
<Data Alias="hdr"/>
<Statements>
<Action Collapsed="true" Name="SetField">
<Argument Name="Field">AllMatched</Argument>
<Argument Name="Value">[newAllMatched]</Argument>
</Action>
</Statements>
</EditRecord>
</Statements>
</If>
</ConditionalBlock>
</Statements>
</LookUpRecord>
</Statements>
</DataMacro>
</DataMacros>
Note that this is an example for updates only. For completeness, one would normally put the above code in a named data macro and call it from After Insert, After Update, and After Delete.

Related

Extracting Text Values from XML in SQL

I'm working with SQL data hosted by a 3rd party, and am trying to pull some specific information for reporting. However, some of what I need to parse out is in XML format, and I'm getting stuck. I'm looking for the syntax to pull the text= values only from the XML code.
I believe the code should something like this, but most of the examples I can find online involve simpler XML hierarchy's than what I'm dealing with.
<[columnnameXML].value('(/RelatedValueListBO/Items/RelatedValueListBOItem/text())[1]','varchar(max)')>
Fails to pull any results. I've tried declaring the spacenames as well, but again...I only ever end up with NULL values pulled.
Example XML I'm dealing with:
<RelatedValueListBO xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://tempuri.org/RelatedValueListBOSchema.xsd">
<Items>
<RelatedValueListBOItem groupKey="Response1" text="Response1" selected="true" />
<RelatedValueListBOItem groupKey="Response2" text="Response2" selected="true" />
<RelatedValueListBOItem groupKey="Response3" text="Response3" selected="true" />
</Items>
</RelatedValueListBO>
Ideally I'd like to pull response1; response2; response3 into a single column. Allowing for the fact that multiple responses may exist. I believe I'm getting stuck with the basic code I've been trying due to the namespaces associated to RelatedValueListBO and the fact that what I want is grouped in groupKey, text, and selected, instead of the value I want just being under the Items node.
You have the namespaces defined in your XML, so you need to define them in the XQuery too.
Fast and dirty method is to replace all namespaces with a "*":
SELECT #x.value('(/*:RelatedValueListBO/*:Items/*:RelatedValueListBOItem/#text)[1]','varchar(max)')
To get all responses in a single column you can use:
SELECT
Item.Col.value('./#text','varchar(max)') X
FROM #x.nodes('/*:RelatedValueListBO/*:Items/*:RelatedValueListBOItem') AS Item(Col)
If you need a better performance, you may need to define namespaces properly.
You can use something like this to extract the value of "text" in the first node of RelatedValueListBOItem
SELECT extractvalue(value(rs), '//RelatedValueListBOItem[1]/#text')
FROM TABLE (xmlsequence(extract(sys.xmltype('<RelatedValueListBO>
<Items>
<RelatedValueListBOItem groupKey="Response1" text="Response1"
selected="true" />
<RelatedValueListBOItem groupKey="Response2" text="Response2"
selected="true" />
<RelatedValueListBOItem groupKey="Response3" text="Response3"
selected="true" />
</Items>
</RelatedValueListBO>'),'/RelatedValueListBO/Items'))) rs;

Name of the user who has processed the cube

There is a code piece in which I have to get the username of the user who has processed the cube or has made any changes in the cube structure.
I have searched in the SSAS DMV's, but didn't find what I needed; I only found the last processed time, but not the name of the user.
Any suggestions?
You can track this using an Extended Event. Add the ProgressReportBegin and ProgressReportEnd events which are for processing. These events include the NTUserName and StartTime fields which you can use to find who processed the cube and when. The Extended Event will need to be running when the cube is processed to capture this. The following is an example XMLA command which can be run when connected to your SSAS database in SSMS to create an Extended Event that tracks cube processing and outputs the results to a file. Of course many of these options are just defaults and you may want to make adjustments as necessary.
https://learn.microsoft.com/en-us/sql/analysis-services/instances/monitor-analysis-services-with-sql-server-extended-events?view=sql-server-2017
<Create xmlns="http://schemas.microsoft.com/analysisservices/2003/engine">
<ObjectDefinition>
<Trace>
<ID>XE_Cube_Process</ID>
<Name>XE_Cube_Process</Name>
<XEvent xmlns="http://schemas.microsoft.com/analysisservices/2011/engine/300/300">
<event_session name="XE_Cube_Process" dispatchLatency="0" maxEventSize="0" maxMemory="4" memoryPartition="none" eventRetentionMode="AllowSingleEventLoss" trackCausality="true" xmlns="http://schemas.microsoft.com/analysisservices/2003/engine">
<event package="AS" name="ProgressReportEnd" />
<event package="AS" name="ProgressReportBegin" />
<target package="package0" name="event_file">
<parameter name="filename" value="C:\Test\XE_Cube_Process.xel" />
<parameter name="max_file_size" value="4096" />
<parameter name="max_rollover_files" value="10" />
<parameter name="increment" value="1024" />
</target>
</event_session>
</XEvent>
</Trace>
</ObjectDefinition>
</Create>

How to import a column from SQL into Excel via BIML

I would like to import column 'Street' (NVARCHAR(50)) from a SQL table (Practice2.dbo.Adress) into Excel (ExcelDestination.xls). I know how to do this in SSIS, but in BIML I can't seem to find the right code, especially to do the column mapping between source and destination. When I try to generate the SSIS package, I get the error
"Could not resolve reference to 'Adress' of type 'TableResource'. 'TableName="Adress"' is invalid. Provide valid scoped name."
Here is what I have done so far:
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<Connections>
<OleDbConnection Name="ConnectionWithPractice2" ConnectionString="Provider='SQLNCLI11'; Data Source='DWH'; Initial Catalog='Practice2'; User Id='system'; Password='password';"></OleDbConnection>
<ExcelConnection Name="Excel Connection Manager" ConnectionString="Provider='Microsoft.Jet.OLEDB.4.0';Data Source='C:\Users\adm-jpna\Documents\ExcelDestination.xls';Extended Properties='Excel 8.0;HDR=Yes;IMEX=1'">
</ExcelConnection>
</Connections>
<Packages>
<Package Name="Package1">
<Tasks>
<Dataflow Name="ImportIntoExcel">
<Transformations>
<OleDbSource Name="OLE_DB_Source" ConnectionName="ConnectionWithPractice2">
<DirectInput>SELECT Street FROM Practice2.dbo.Adress</DirectInput>
</OleDbSource>
<ExcelDestination Name="Excel_Destination" ConnectionName="Excel Connection Manager">
<Columns>
<Column SourceColumn="Street"></Column>
</Columns>
<TableOutput TableName="Adress"></TableOutput>
</ExcelDestination>
</Transformations>
</Dataflow>
</Tasks>
</Package>
</Packages>
I made a few minor changes to your ExcelDestination
<Package Name="so_45063165">
<Tasks>
<Dataflow Name="ImportIntoExcel">
<Transformations>
<OleDbSource Name="OLE_DB_Source" ConnectionName="ConnectionWithPractice2">
<DirectInput>SELECT N'123 Oak' AS Street;</DirectInput>
</OleDbSource>
<ExcelDestination Name="Excel_Destination" ConnectionName="Excel Connection Manager">
<ExternalTableOutput Table="Sheet1$" />
</ExcelDestination>
</Transformations>
</Dataflow>
</Tasks>
</Package>
TableOutput refers to the Biml collection of Tables. You're looking for ExternalTableOutput which instructs the engine to look to the referred object (Excel in this case) to validate that it exists. The change in tag results in the property changing from TableName to Table and then since we're referencing a worksheet and not a table, we need to specify as such with a $. Sheet1 would be a table or named ranged while Sheet1$ means the actual worksheet.
Since you didn't provide a column mapping between your source Street and a target column, I removed the tags.

multiple joins in fetchxml involving more than 2 entities

I have three entities
Case - new_welfarecases
Goal - new_casegoal
Activity - new_welfarecaseactivity
Now each Case will have multiple Goals and each Goal will have multiple Activities(N:1)
In the goal entity, new_caseid is the lookup field for Case
The case has a business process flow defined and the flow has stages like initiation, moved to next level etc
The stage of the goal is captured in field called new_startstageofthecase
To get list of goals for a case in particular stage I use the below fetchxml
var fetchXml = "<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>"
+"<entity name='new_casegoal'>"
+"<attribute name='new_startstageofthecase' />"
+"<filter type='and'>"
+"<condition attribute='new_startstageofthecase' operator='"+ goalFilterOption +"' value='" + currentStageId +"' />"
+"</filter>"
+"</entity>"
+ "</fetch>";
Subgrid.control.SetParameter("fetchXml", fetchXml); //set the fetch xml to the sub grid
Now I want to retrieve the list of activities for a case in particular stage, how can I fetch them?
Activities entity does not have the stage field, but it has to be fetched from the goal it is associated to.
The lookup for goal in activity entity is new_childwelfarecasegoalid
Everytime I need to build those queries I go to the Advanced Find in CRM.
1) Start with an advanced find to look for Activities.
2) Then add a join to Goal entity (Related Entities -> Goal),
3) Then, add a join from Goal to the Record entity.
You can add as many filters on each of the entities. In your case a filter for the specific Stage and Record.
Then export the resulting FetchXml from the View.
As I understand you, you want to:
Fetch Activities that have a Goal that has an Record.
The Record should be a specific Record.
The Record should have a specific stage in the BPF.
A query along those lines would look like:
<fetch version='1.0' mapping='logical' distinct='false'>
<entity name="new_Activity">
<all-attributes />
<link-entity name="new_Goal" from="new_goalid" to="new_goal">
<link-entity name="new_Record" from="new_recordid" to="new_record">
<filter type="and">
<condition attribute="new_recordid" operator="eq" value="{<record-guid-here>}" />
</filter>
<link-entity name="processstage" from="processstageid" to="stageid">
<filter type="and">
<condition attribute="stagename" operator="eq" value="<stage-name-here>" />
</filter>
</link-entity>
</link-entity>
</link-entity>
</entity>
</fetch>

vxml: defining grammars with equivalent inputs

I am using an engine based on TellMe. I have seen examples of grammars where the user can say one of a few different things that are considered the same. However, all the examples i've seen have been for in-line grammars (which dont work with the vxml engine im using). I want to know how i can change my .grxml file to do this. This is the file:
<?xml version="1.0"?>
<!-- created by Matthew Murdock. Grammars for speech rec menus -->
<grammar xmlns="http://www.w3.org/2001/06/grammar" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3.org/2001/06/grammar http://www.w3.org/TR/speech-grammar/grammar.xsd" xml:lang="en" version="1.0" mode="voice" scope="dialog" tag-format="semantics/1.0.2006">
<rule id="keep">
<one-of>
<item>exit</item>
<item>exit the system</item>
<item>another</item>
<item>another mailbox</item>
<item>play</item>
<item>play back</item>
</one-of>
</rule>
</grammar>
instead of having 6 items, i want to have 3 items, each having two possible utterances. Any ideas on how i can do this?
A more compact form:
<rule id="exit">
exit <item repeat="0-1">the system</item>
<tag>out.result = "exit"</tag>
</rule>
<rule id="play">
play <item repeat="0-1">back</item>
<tag>out.result = "play"</tag>
</rule>
The answers you want are in the SISR specification which provides a mechanism for attaching meaning to input paths. Rewriting your example:
<?xml version="1.0"?>
<grammar xmlns="http://www.w3.org/2001/06/grammar" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3.org/2001/06/grammar http://www.w3.org/TR/speech-grammar/grammar.xsd" xml:lang="en" version="1.0" mode="voice" scope="dialog" tag-format="semantics/1.0-literals">
<rule id="keep">
<one-of>
<item>
<one-of>
<item>exit</item>
<item>exit the system</item>
</one-of>
<tag>exit</tag>
</item>
<item>
<one-of>
<item>another</item>
<item>another mailbox</item>
</one-of>
<tag>another</tag>
</item>
<item>
<one-of>
<item>play</item>
<item>play back</item>
</one-of>
<tag>play</tag>
</item>
</one-of>
</rule>
</grammar>
Several things to know:
I chose the literal tag format (notice the tag-format attribute of the grammar element). It could have also been implemented using "semantics/1.0" and the contents of the tag would have looked like: out="exit";
TellMe tag-format values may need to be different, but their development guide implies they follow the standards.
Once you have it working, don't hesitate to create filler grammars (in SRGS speak, rules). Filler rules would be rules without any SI (no tag elements) and contain common phrases people add to responses. For example, a trailing rule that could be added at the end of your grammar:
</one-of>
<item repeat="0-1"><ruleref uri="#trailing"/></item>
</rule>
<rule id="trailing>
<one-of>
<item>please</item>
<item>thank you</item>
</one-of>
</rule>
</grammar>
This would support more natural types of responses. This may or may not be important depending on your calling base. Filler grammars can be very large, but tend to be highly reusable. You can also add filler at the beginning of input. In rich speech applications, a the most significant gain in the tuning process involves updating the grammar to contain the actual phrases spoken by the caller versus what the developer or VUI designer thought would be spoken.
I figured it out. I changed my grammar to look like this:
<?xml version="1.0"?>
<grammar xmlns="http://www.w3.org/2001/06/grammar" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.w3.org/2001/06/grammar http://www.w3.org/TR/speech-grammar/grammar.xsd" xml:lang="en" version="1.0" mode="voice" scope="dialog" tag-format="semantics/1.0-literals">
<rule id="keep">
<one-of>
<item><ruleref id="#exit"/></item>
<item><ruleref id="#play"/></item>
</one-of>
</rule>
<rule id="exit">
<one-of>
<item>exit</item>
<item>exit the system</item>
</one-of>
<tag>out.result = "exit"</tag>
</rule>
<rule id="play">
<one-of>
<item>play</item>
<item>play back</item>
</one-of>
<tag>out.result = "play"</tag>
</rule>
</grammar>
Then, back in my script instead of basing my actions on callerInput (the variable specified in the <field> tag), i based them off of callerInput$.interpretation which holds xml containing whatever i assigned out.result to in the <tag> element of the grammar.
I guess it makes sense to base your actions on the "interpretation" and not the caller's literal input.
NOTE: Because we are working with our own vxml engine we were able to create a method for extracting the interpretation value out of the xml.