How can I convert this T-SQL to Fetch-XML? - tsql

I want to use this SQL in a Dynamics CRM report. I can't work out how to convert it to Fetch-XML.
select p.ProductNumber "Plan Number",p.Name,p.price "Monthly Rate",count(*) "Group", '0' "Direct Debit"
from contact c,product p
where c.integ_schemeid = p.ProductId
and c.ParentCustomerId is not null
group by p.ProductNumber,p.Name,p.price
union
select p.ProductNumber "Plan Number",p.Name,p.price "Monthly Rate", '0' "Group", count(*) "Direct Debit"
from contact c,product p
where c.integ_schemeid = p.ProductId
and c.ParentCustomerId is null
group by p.ProductNumber,p.Name,p.price
http://www.sql2fetchxml.com fails on this occasion.

You can't convert that query to FetchXML, because unions aren't supported. What you'll need to do is look into merging the queries into 1 if possible. Even if it means duplicating columns and using conditional statements within your report to display the relevant data instead. For example, if you simplified the query to this:
select p.ProductNumber "Plan Number", p.Name, p.price, c.ParentCustomerId
from product p
inner join contact c on c.integ_schemeid = p.ProductId
This can be converted to the following fetchxml:
<fetch mapping="logical">
<entity name="product">
<attribute name="ProductNumber" alias="Plan Number" />
<attribute name="Name" />
<attribute name="price" />
<link-entity name="contact" to="ProductId" from="integ_schemeid" alias="c" link-type="inner">
<attribute name="ParentCustomerId" />
</link-entity>
</entity>
</fetch>
Then, because you have all of the data in 1 dataset including contacts with null ParentCustomerIds, you can group within your report instead of within the query.

Related

parameters in sql fragment substitute error

I write a sql fragment, like this:
<sql id="day">
<choose>
<when test="${property} == 'day'">
substring(datachange_createtime, 1, 10)
</when>
<otherwise>
${property}
</otherwise>
</choose>
</sql>
and include this sql like this:
select * from my_table
<if test="groupBy != null">
group by
<foreach collection="groupBy" item="groupByAttr" separator=",">
<include refid="day">
<property name="property" value="groupByAttr"/>
</include>
</foreach>
</if>
But I got an error, mybatis didn't substitute property with a real parameter, but with groupByAttr. The result sql is like:
select * from my_table group by groupByAttr
In the otherwise clause, if I replace ${property} with #{${property}}, The result sql becomes:
select * from my_table group by ?
It is indeed correct, but for some reasons, I don't want a prepared sql.
I think the problem is the behavior of substitution in test and otherwise clauses is different.
Is the a bug, or just some mistakes I took? How to solve this problem?
Short answer:
You need to change the <include /> as follows.
<sql id="day">
<choose>
<when test="${property} == 'day'">
substring(datachange_createtime, 1, 10)
</when>
<otherwise>
\\${${property}}
</otherwise>
</choose>
</sql>
Long answer:
With your original code, the statement will look as follows after the <include /> substitution.
select * from my_table
<if test="groupBy != null">
group by
<foreach collection="groupBy" item="groupByAttr" separator=",">
<choose>
<when test="groupByAttr == 'day'">
substring(datachange_createtime, 1, 10)
</when>
<otherwise>
groupByAttr
</otherwise>
</choose>
</foreach>
</if>
As you can see, <when /> is OK, but <otherwise /> is not.
<otherwise /> should look like this:
<otherwise>
${groupByAttr}
</otherwise>
In the expression in the short answer \\${${property}}, the first two backslashes is the escape syntax which avoids the outer ${} from being treated as a variable.
Note that #{groupByAttr} does not work here because, in java.sql.PreparedStatement, a placeholder ? is not allowed for a table/column name.
Please see the wiki page for the details.

Postgres XML parsing - Calculate the sum of multiple nodes of the same name using XPath

I have an xml snippet as below:
<OpCodeLaborInfo JobStatus="F" UpSellFlag="N" JobNo="1" OpCode="02TTZ10K" OpCodeDesc="10K SERVICE">
<TechInfo ActualHrsWorked="2.50" CustTechRate="27.00" TechHrs="0.00" TechName="JEFF SELLERS" TechNo="4816" />
<TechInfo ActualHrsWorked="0.00" CustTechRate="27.00" TechHrs="0.70" TechName="JEFF SELLERS" TechNo="4816" />
<BillTimeRateHrs BillRate="129.97" />
<CCCStmts Correction="PERFORMED 10K SERVICE" Complaint="LUBE OIL FILTER CHANGE, TIRE ROTATION, PERFORM MULTI POINT" />
<CCCStmts Correction="X" Complaint="INSPECTION, INSPECT FILTERS AND RECOMMEND, INSPECT BRAKES," />
<CCCStmts Complaint="BELTS AND HOSES" />
<RoAmts DlrCost="18.90" PayType="Cust" AmtType="Job" TotalAmt="59.12" />
</OpCodeLaborInfo>
<OpCodeLaborInfo JobStatus="F" UpSellFlag="N" JobNo="2" OpCode="02TTZ10K" OpCodeDesc="10K SERVICE">
<TechInfo ActualHrsWorked="2.50" CustTechRate="27.00" TechHrs="1.00" TechName="JEFF SELLERS" TechNo="4816" />
<TechInfo ActualHrsWorked="0.00" CustTechRate="27.00" TechHrs="0.00" TechName="JEFF SELLERS" TechNo="4816" />
<BillTimeRateHrs BillRate="129.97" />
<CCCStmts Correction="PERFORMED 10K SERVICE" Complaint="LUBE OIL FILTER CHANGE, TIRE ROTATION, PERFORM MULTI POINT" />
<CCCStmts Correction="X" Complaint="INSPECTION, INSPECT FILTERS AND RECOMMEND, INSPECT BRAKES," />
<CCCStmts Complaint="BELTS AND HOSES" />
<RoAmts DlrCost="18.90" PayType="Cust" AmtType="Job" TotalAmt="59.12" />
</OpCodeLaborInfo>
I need to calculate the sum of the TechInfo/#TechHrs for each OpCodeLaborInfo. I tried the following:
unnest(xpath('sum(//dns:RepairOrder/dns:RoRecord/dns:Rolabor/dns:OpCodeLaborInfo/dns:TechInfo/#TechHrs[1])'::text,
data_detail.ro_data_xml,
ARRAY[ARRAY['dns'::text, 'http://www.starstandards.org/STAR'::text]]))::text::numeric AS lbrsoldhours
but this seems to return the sum of the Tech Hours inside both the OpCodeLaborInfo nodes. Could someone be able to tell me how I can tweak the xpath so as to get the desired result.
So basically I need :
Job
Tech Hrs
1
sum(0.00+0.70)
2
sum(1.00+0.00)
I would solve this using xmltable()
select d.job, sum(t.hours)
from data_detail d
cross join xmltable (
'/OpCodeLaborInfo/TechInfo'
passing d.ro_data_xml
columns hours numeric path '#TechHrs') as t
group by d.job;
Online example
The XPath is probably not correct as the XPath you have shown doesn't match your sample XML data. Your sample XML also doesn't contain a namespace, so I am not sure why you are passing one to xpath()
But if you need one, you can use something like this:
cross join xmltable (
xmlnamespaces ('http://www.starstandards.org/STAR' as dns),
'/dns:OpCodeLaborInfo/dns:TechInfo'
passing d.ro_data_xml
columns hours numeric path '#TechHrs') as t
xpath can also work fine:
SELECT job
, SUM((xpath('//#TechHrs', element))[1]::text::decimal)
FROM data_detail
, LATERAL (SELECT unnest(xpath('/OpCodeLaborInfo/TechInfo', ro_data_xml))) u(element)
GROUP BY job;
fiddle
(based on the fiddle of #a_horse_with_no_name)

Mybatis When test condition with Internal query

I am looking for a query where i can use either internal query returned value or direct SQL in when test= in Mybatis.
<foreach item="ID"
index="index"
collection="selectionIds"
separator=";">
UPDATE TABLE_1 SET
ACT_IND ='N', upd_by = 1234
WHERE SLCT_ID = #{ID}
AND rem= select REM from TABLE_1 where SLCT_ID=#{ID}
<choose>
<when test="rem == 3">
AND Bbsid=#{nsid}
</when>
<otherwise>
AND asid=#{asid}
</otherwise>
</choose>
</foreach>
From the above query, how can i get the rem value and use in when condition.
Thanks

Editor extensions for SQL Developer

I'm attempting to write an (editor) extension for Oracle SQL Developer. I'm having trouble finding information about it, but I've pieced the following together from the few tutorials and blog entries that I've found:
<?xml version="1.0" encoding="UTF-8"?>
<displays>
<display enable="true" objectType="SEQUENCE" style="null" type="editor">
<name><![CDATA[Details]]></name>
<query>
<sql>
<![CDATA[
SELECT 'sequence_name' AS "NAME", sequence_name AS "VALUE" FROM :NAME
UNION
SELECT 'last_value' AS "NAME", CAST(last_value AS text) AS "VALUE" FROM :NAME
UNION
SELECT 'start_value' AS "NAME", CAST(start_value AS text) AS "VALUE" FROM :NAME
UNION
SELECT 'increment_by' AS "NAME", CAST(increment_by AS text) AS "VALUE" FROM :NAME
UNION
SELECT 'max_value' AS "NAME", CAST(max_value AS text) AS "VALUE" FROM :NAME
UNION
SELECT 'min_value' AS "NAME", CAST(min_value AS text) AS "VALUE" FROM :NAME
UNION
SELECT 'cache_value' AS "NAME", CAST(cache_value AS text) AS "VALUE" FROM :NAME
UNION
SELECT 'log_cnt' AS "NAME", CAST(log_cnt AS text) "VALUE" FROM :NAME
UNION
SELECT 'is_cycled' AS "NAME", CAST(is_cycled AS text) AS "VALUE" FROM :NAME
UNION
SELECT 'is_called' AS "NAME", CAST(is_called AS text) AS "VALUE" FROM :NAME
]]>
</sql>
</query>
<CustomValues>
<TYPE>vertical</TYPE>
</CustomValues>
</display>
</displays>
This works, in that extra tabs do show up for sequences on Oracle db connections. However, they do not show up for Postgres db connections. For sequences to even show in pg databases in SQL Dev, I have to use a second extension script:
<?xml version="1.0" encoding="windows-1252" ?>
<navigator RESOURCE_FILE="oracle.dbtools.raptor.navigator.OracleNavigatorResource" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="navigator.xsd">
<objectType connType="PostgreSQL" id="SEQUENCE" includesSyns="true" weight="100.0">
<folder>
<icon RSKEY="SEQUENCE_FOLDER_ICON"/>
<label RSKEY="Sequences"/>
<queries>
<query minversion="8">
<sql constrained="true"><![CDATA[SELECT relname, nspname FROM pg_class JOIN pg_namespace ON pg_namespace.oid = pg_class.relnamespace WHERE relkind = 'S' AND nspname = :SCHEMA]]></sql>
</query>
<columns>
<column filterable="true" id="SEQUENCENAME" sortable="true">
<colName><![CDATA[relname]]></colName>
</column>
<column filterable="true" id="NAME" sortable="true">
<colName><![CDATA[relname]]></colName>
</column>
</columns>
</queries>
</folder>
<node>
<icon RSKEY="OracleIcons.SEQUENCE"/>
</node>
</objectType>
</navigator>
Is there a way to specify that this extension only applies to Postgres sequences, and not to Oracle sequences?
The correct answer here seems to be to have a connType="PostgreSQL" attribute in the display element. This limits it to only Postgres sequences. This was trial and error, I can't find editor.xsd and it seems like Oracle doesn't make it available.

Adding an entity key when no key is inferred from a view

I have a database view which joins across a number of tables in SQL Server 2005. It looks something like this:
SELECT
m1.MenuName AS menu_name, m2.MenuName AS sub_menu_name, p.ProductName, od.amount
FROM
dbo.tblMenus AS m1
FULL OUTER JOIN
dbo.tblMenus AS m2
FULL OUTER JOIN
dbo.tblProductsRelMenus AS pm ON m2.Id = pm.SubMenuId ON m1.Id = pm.MenuId
FULL OUTER JOIN
(SELECT
dbo.tblOrderDetails.ProductId, SUM(dbo.tblOrderDetails.Ammount) AS amount
FROM
dbo.tblOrderDetails
FULL OUTER JOIN
dbo.tblOrders AS o ON dbo.tblOrderDetails.OrderId = o.OrderId
WHERE (o.OrderDestroyed = 0)
GROUP BY dbo.tblOrderDetails.ProductId) AS od
RIGHT OUTER JOIN
dbo.tblProducts AS p ON od.ProductId = p.ProductId ON pm.ProductId = p.ProductId
When I try to create an ADO .Net entity data model it complains about not having a primary key in the SSDL secion. I then found this:
http://msdn.microsoft.com/en-us/library/dd163156.aspx
but I don't understand the part about a defining query. Surely I just want a column with unique numbers to define the key, or?
<EntityType Name="SoldItemsView">
<Key>
<PropertyRef Name="SoldItemsViewId" />
</Key>
<Property Name="SoldItemsView" Type="int" Nullable="false" />
<Property Name="menu_name" Type="nvarchar" MaxLength="100" />
<Property Name="sub_menu_name" Type="nvarchar" MaxLength="100" />
<Property Name="ProductName" Type="nvarchar" MaxLength="50" />
<Property Name="amount" Type="int" />
</EntityType>
But how do I populate this column with unique numbers?
Thanks,
Barry
You can use only columns from the view. To define an entity key you must select column (or set of columns) from your view which uniquely identifies record from the view.