Counting rows with the same attributes XML/SQL - sql

Started doing some SQL/XML resently but i have the problem of doing count functions.
Lets say i have the database
<Root>
<Element ATTTRIBUTE1 ="A" ATTRIBUTE2="1" />
<Element ATTRIBUTE1 ="A" ATTRIBUTE2="1" />
<Element ATTRIBUTE1 ="A" ATTRIBUTE2="1" />
<Element ATTRIBUTE1 ="A" ATTRIBUTE2="1" />
<Element ATTRIBUTE1 ="A" ATTRIBUTE2="1" />
<Element ATTRIBUTE1 ="A" ATTRIBUTE2="3" />
<Element ATTRIBUTE1 ="A" ATTRIBUTE2="3" />
<Element ATTRIBUTE1 ="B" ATTRIBUTE2="3" />
<Element ATTRIBUTE1 ="B" ATTRIBUTE2="3" />
<Element ATTRIBUTE1 ="B" ATTRIBUTE2="3" />
<Element ATTRIBUTE1 ="B" ATTRIBUTE2="3" />
<Element ATTRIBUTE1 ="C" ATTRIBUTE2="4" />
<Element ATTRIBUTE1 ="C" ATTRIBUTE2="4" />
</Root>
What can i write in SLQ/XML to make it count how many of each i have that have the two same attributes? So for example i have 5 elements of with attributes A and 1, 2 attributes of A and 3 and two attributes of B and 3 and so on.
I have tried to group them but i kind of just split them up outside the root then.

Related

Q. How to select named element values from XSD string field

Within SQL Server I'm trying to select values from what I think is a XSD string.
e.g. Given the following SQL Server table
CREATE TABLE dbo.TextXML (
ID INT PRIMARY KEY,
Data NVARCHAR(max))
INSERT INTO dbo.TextXML ( ID, Data )
SELECT 1,
('<element name="Rownum" value="Row23" />
<element name="CONNECTIONTYPESECTION" value="True" />
<element name="CustomFields" />
<element name="EchoData">
<element name="0000" value="8220000000000000" />
<element name="0001" value="0400000100000000" />
<element name="0007" value="0805193143" />
<element name="MessageType" value="1234" />
</element>
<element name="ENABLESSL" value="false" />' )
INSERT INTO dbo.TextXML ( ID, Data )
SELECT 2,
('<element name="Rownum" value="Row24" />
<element name="CONNECTIONTYPESECTION" value="True" />
<element name="CustomFields" />
<element name="EchoData">
<element name="0000" value="8220000000000000" />
<element name="0001" value="0400000100000000" />
<element name="0007" value="0805193143" />
<element name="MessageType" value="5678" />
</element>
<element name="ENABLESSL" value="true" />' );
I want to be able to select the values for given element names. Something like ...
SELECT ID, Data.CONNECTIONTYPESECTION, Data.EchoData.0007, Data.EchoData.MessageType, Data.ENABLESSL
FROM TextXML
WHERE Data.Rownum = "Row23" AND Data.EchoData.MessageType = "1234".
ID Data.CONNECTIONTYPESECTION Data.EchoData.0007 Data.EchoData.MessageType Data.ENABLESSL
1 True 0805193143 1234 true
I can use CHARINDEX and SUBSTRING but have to hardcode the length of the "name" value and this asumes the "value" is always the same length. I'm hoping there is a better and more efficient way do do this.
I have experimented with CROSS APPPLY and XML VALUE functions but this only returns the first element in the Data field. I also could not find out how to search for a particular element "name" to get its value
Please try the following T-SQL.
-- DDL and sample data population, start
DECLARE #tbl TABLE (ID INT IDENTITY PRIMARY KEY, Data NVARCHAR(max));
INSERT INTO #tbl (Data) VALUES
(N'<element name="Rownum" value="Row23"/>
<element name="CONNECTIONTYPESECTION" value="True"/>
<element name="CustomFields"/>
<element name="EchoData">
<element name="0000" value="8220000000000000"/>
<element name="0001" value="0400000100000000"/>
<element name="0007" value="0805193143"/>
<element name="MessageType" value="1234"/>
</element>
<element name="ENABLESSL" value="false"/>'),
(N'<element name="Rownum" value="Row24"/>
<element name="CONNECTIONTYPESECTION" value="True"/>
<element name="CustomFields"/>
<element name="EchoData">
<element name="0000" value="8220000000000000"/>
<element name="0001" value="0400000100000000"/>
<element name="0007" value="0805193143"/>
<element name="MessageType" value="5678"/>
</element>
<element name="ENABLESSL" value="true"/>');
-- DDL and sample data population, end
;WITH rs AS
(
SELECT *
, TRY_CAST(data AS XML) AS xmldata
FROM #tbl
)
SELECT rs.ID
, xmldata.value('(element[#name="CONNECTIONTYPESECTION"]/#value)[1]','VARCHAR(10)') AS CONNECTIONTYPESECTION
, xmldata.value('(element[#name="EchoData"]/element[#name="0007"]/#value)[1]','VARCHAR(10)') AS [EchoData.0007]
, xmldata.value('(element[#name="EchoData"]/element[#name="MessageType"]/#value)[1]','VARCHAR(10)') AS [EchoData.MessageType]
, xmldata.value('(element[#name="ENABLESSL"]/#value)[1]','VARCHAR(10)') AS [Data.ENABLESSL]
FROM rs
WHERE xmldata.value('(element[#name="Rownum"]/#value)[1]','VARCHAR(30)') = 'Row23'
AND xmldata.value('(element[#name="EchoData"]/element[#name="MessageType"]/#value)[1]','VARCHAR(10)') = '1234';
Output
+----+-----------------------+---------------+----------------------+----------------+
| ID | CONNECTIONTYPESECTION | EchoData.0007 | EchoData.MessageType | Data.ENABLESSL |
+----+-----------------------+---------------+----------------------+----------------+
| 1 | True | 0805193143 | 1234 | false |
+----+-----------------------+---------------+----------------------+----------------+

Sql server xpath conditionnal query

I have a table where one field called 'configuration' is type of XML:
<configuration>
<element value="john" />
<element value="kevin" />
<element value="lisa" />
<element value="david" />
<element value="mike" />
</configuration>
What I would like to do, is to retrieve all the table records or at least count the table records that have a field 'configuration' containing at least one 'element' attribute containing a 'value' attribute equals to 'lisa'.
What I have for the moment, is a query that can retrieve the 'value' attribute of the specified 'element' position, for example:
select Configuration.value('(/configuration/element/#value)[0]', 'nvarchar(max)') // returns me 'john'
select Configuration.value('(/configuration/element/#value)[1]', 'nvarchar(max)') // returns me 'kevin'
This is a bit of pseudo-SQL in the absence of a dataset, and a bit of guesswork; in that I (think) you simply want to return the rows(?) where there is a the node configuration/element has the value property 'lisa'. IF my guess is right, then something like this will work (you'll ened to replace object names in Braces({}):
SELECT {Columns}
FROM [{Your Table}] YT
WHERE EXISTS (SELECT 1
FROM [{Your Table}] E
CROSS APPLY E.[{Your XML Column}].nodes('configuration/element') C(E)
WHERE E.[{Your ID Column}] = YT.[{Your ID Column}]
AND C.E.value('./#value','varchar(50)') = 'lisa');
Example:
WITH VTE AS(
SELECT 1 AS ID,
CONVERT(xml,'<configuration>
<element value="john" />
<element value="kevin" />
<element value="lisa" />
<element value="david" />
<element value="mike" />
</configuration>') AS XMlCol
UNION ALL
SELECT 2 AS ID,
CONVERT(xml,'<configuration>
<element value="craig" />
<element value="donald" />
<element value="jenny" />
<element value="jayne" />
</configuration>') AS XMlCol)
SELECT *
FROM VTE YT
WHERE EXISTS (SELECT 1
FROM VTE E
CROSS APPLY E.XMlCol.nodes('configuration/element') C(E)
WHERE E.ID = YT.ID
AND C.E.value('./#value','varchar(50)') = 'lisa');
This only returns the row with an ID of 1.
Please try the below,
declare #xml as xml
set #xml='<configuration>
<element value="john" />
<element value="kevin" />
<element value="lisa" />
<element value="david" />
<element value="mike" />
</configuration>'
SELECT T.c.value('./#value','nvarchar(250)' ) As element
FROM #xml.nodes('//element') AS T(c)

Update Single XML Node Value of XML Column using SQL Server

I want to update single value of XML Node in SQl Server
Below is the table structure
XML Structure
<PayDetails>
<Column Name="FG" DataType="float" Value="7241" />
<Column Name="SKILL" DataType="float" Value="3" />
<Column Name="PI" DataType="float" Value="87" />
<Column Name="MD" DataType="float" Value="30" />
<Column Name="LD" DataType="float" Value="4" />
<Column Name="WEEKOFF_DAYS" DataType="float" Value="4" />
<Column Name="NETPAY" DataType="float" Value="5389" />
</PayDetails>
I want to update value of FG from 7241 to 8000
You want to use replace value of...with keywords:
Try something like the following:
update tablename
set TransactionFieldDetails.modify(
'replace value of
(/PayDetails/Column[#Name="FG"]/#Value)[1]
with "8000"');

performance is slow while running a DB query using Struts

I am using Struts to build a web application. Application server is Tomcat Server 6, database is Oracle 11G. I am executing an action class which contains the following DB query:
SELECT BV_USER__TEMP.CEC_ID AS USER_ID,
BV_USER_BEHRCHY_TEMP.LEVEL_NUM AS LEVEL_NUM,
BV_IAM_BUSINESS_ENTITY_HIER.BUSINESS_ENTITY_HIER_NAME AS IAM__HIER_NAME,
'Total Development' AS TOTAL_ENGINEERING,
BV_IAM_BUSINESS_ENTITY_HIER.BUSINESS_HIER_NAME AS keyCol,
BV_USER_BE_HRCHY_TEMP.BUSINESS_ENTITY_DESCR AS val
FROM BV_IAM_BUSINESS_ENTITY_HIER IAM
INNER JOIN BV_SUB_BUSINESS_ENTITY BSE
ON (BV_USER_BE_HRCHY_TEMP.SUB_BUSINESS_ENTITY_DESCR =
BV_IAM_BUSINESS_ENTITY_HIER.BUSINESS_ENTITY_HIER_NAME)
WHERE IAM_ROLE_NAME='FIN BI_USER LEVEL ACCESS'
AND IAM_LEVEL_NUM=2
AND USER_ID=?
GROUP BY 1,2,3,4,5,6
UNION ALL
SELECT CEC_ID AS USER_ID,
BUSINESS_ENTITY_HIER_NAME.IAM_LEVEL_NUM AS LEVEL_NUM,
BUSINESS_ENTITY_HIER_NAME AS keyCol,
BV_USER_BE_HRCHY_TEMP.BUSINESS_ENTITY_DESCR AS val
FROM BV_IAM_BUSINESS_ENTITY_HIER IAM
INNER JOIN BV_SUB_BUSINESS_ENTITY BSE
ON (BUSINESS_ENTITY_NAME=BUSINESS_ENTITY_HIER_NAME)
WHERE BV_IAM_BUSINESS_ENTITY_HIER.IAM_ROLE_NAME='FIN BI_USER LEVEL ACCESS'
AND BV_IAM_BUSINESS_ENTITY_HIER.IAM_LEVEL_NUM=1
AND USER_id=2
GROUP BY 1,2,3,4,5,6
UNION ALL
SELECT BV_USER_BE_HRCHY_TEMP.USER_ID,
BV_IAM_BUSINESS_ENTITY_HIER.IAM_LEVEL_NUM AS LEVEL_NUM,
BV_IAM_BUSINESS_ENTITY_HIER.BUSINESS_ENTITY_HIER_NAME AS IAM_ENTITY_HIER_NAME,
'Total Development' AS TOTAL_ENGINEERING,
BUSINESS_ENTITY_HIER_NAME AS keyCol,
BV_USER_BE_HRCHY_TEMP.BUSINESS_ENTITY_DESCR AS val
FROM BV_IAM_BUSINESS_ENTITY_HIER IAM
CROSS JOIN BV_USER_BE_HRCHY_TEMP.SUB_BUSINESS_ENTITY_DESCR BSE
WHERE BV_IAM_BUSINESS_ENTITY_HIER.IAM_ROLE_NAME='FIN BI_USER LEVEL ACCESS'
AND BV_IAM_BUSINESS_ENTITY_HIER.IAM_LEVEL_NUM=0
AND USER_ID=?
GROUP BY 1,2,3,4,5,6;
In applicationContext.xml the bean:
<bean id="tablOrclDataSourceRead" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver" />
<property name="url" value="jdbc:oracle:oci:#********DEV" />
<property name="username" value="username" />
<property name="password" value="password" />
<property name="initialSize" value="5" />
<property name="maxActive" value="5" />
<property name="maxIdle" value="0" />
<property name="minIdle" value="0" />
<property name="maxWait" value="-1" />
</bean>
JSON returned:
{"data":[
{"keyCol":"Utah","val":"Utah"},
{"keyCol":"Seattle","val":"Seattle"},
{"keyCol":Nebraska","val":"Nebraska"},
{"keyCol":"Enterprise Networking","val":"Enterprise Networking"}
]}
The time taken to execute the action (and return the JSON) with the above query is around 21 seconds.
Please let me know if I am missing something.
The same query when executed through SQL developer returns the result set in less than a second.

Add text to the start of a SOLR database value

I am using this code for my SOLR DIH:
<dataConfig>
<dataSource name="app" driver="org.postgresql.Driver" url="jdbc:postgresql://localhost:5432/wikipedia" user="wikipedia" password="secret" />
<dataSource name="data" driver="org.postgresql.Driver" url="jdbc:postgresql://localhost:5432/wikipedia" user="wikipedia" password="secret" />
<document>
<entity dataSource="app-ds" name="item" query="SELECT id, title, description, date, link, location_id, source_id, company_id from item">
<field column="id" name="id" />
<field column="title" name="title" />
<field column="description" name="description" />
<field column="date" name="date" />
<field column="link" name="link" />
<entity dataSource="app-ds" name="location" query="SELECT name, coordinate from location where location_id=${item.location_id}">
<field column="name" name="location_name" />
<field column="coordinate" name="location_coordinates" />
</entity>
<entity dataSource="app-ds" name="source" query="SELECT name from source where source_id=${item.source_id}">
<field column="name" name="source_name" />
</entity>
<entity dataSource="app-ds" name="company" query="SELECT name from company where company_id=${item.company_id}">
<field column="name" name="company_name" />
</entity>
</entity>
</document>
</dataConfig>
Since I am merging two databases I want to have a uniqueID for each entry within SOLR. In my case the best way of doing this is to have app*ID* for the first databases ID's and data*ID* for the second databases ID's.
Using my code above, how do I add the word "app" to the front of the ID that is stored in the SOLR ID field so that my database ID=123 and the Solr ID = app123
EDIT: As I guess it might be something like this (but I am not good with SQL)
query="SELECT app_(id)
You can try to modify the SQL Query as -
SELECT 'TABLE1' || ID AS PRIMARY_ID ........
PRIMARY_ID can be now configured as unique ID in solr.
<field column="primary_id" name="primary_id" />
Even if you are performing incremental updates using Delta imports, the SQL ID updated would still generate the Same Solr ID with the above query and would be updated. So be sure to use the above in the Delta queries as well.