July 12, 2011 at 5:29 am
Hi All,
I need your advise, please. I have to extract a very simple data from a SQL: one main table and one linked -
customer's site and its equipment. Using Oracle it was very easy to achieve what I need using XMLAGG / XMLFOREST, but I am straggling with SQL 2008 and your help will be more than appropriated, please.
(1) The outcome I need is as follow
<?xml version="1.0" encoding="ISO-8859-1" standalone="no" ?>
<ns1:site_equipment xmlns:ns1="ns0:cape_site" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<site_code>2E1012</site_code>
<erected_equipment_list>
<equipment_code>S1307</equipment_code>
<erected_qnty>3658</erected_qnty>
</erected_equipment_list>
<erected_equipment_list>
<equipment_code>S1308</equipment_code>
<erected_qnty>1685</erected_qnty>
</erected_equipment_list>
<erected_equipment_list>
<equipment_code>S1309</equipment_code>
<erected_qnty>356</erected_qnty>
</erected_equipment_list>
<erected_equipment_list>
<equipment_code>S215</equipment_code>
<erected_qnty>806</erected_qnty>
</erected_equipment_list>
</ns1:site_equipment>
(2) To achieve it I have tried so far:
WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema-instance' AS xsi,
'http://www.w3.org/2001/XMLSchema' AS xsd,
'ns0:cape_site' AS ns1)
SELECT jc.WBSNumber "site_code",
jst.EquipmentNo "erected_equipment_list/equipment_code",
jst.Qty "erected_equipment_list/erected_qnty"
FROM Job_Stock_Tbl jst
JOIN Job_Card jc
ON jc.CapeId = jst.CapeId
FOR XML PATH(''), ROOT ('ns1:site_equipment');
But got an output like this:
<ns1:site_equipment xmlns:ns1="ns0:cape_site" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<site_code>2E1012</site_code>
<erected_equipment_list>
<equipment_code>S1307</equipment_code>
<erected_qnty>3658</erected_qnty>
</erected_equipment_list>
<site_code>2E1012</site_code>
<erected_equipment_list>
<equipment_code>S1308</equipment_code>
<erected_qnty>1685</erected_qnty>
</erected_equipment_list>
<site_code>2E1012</site_code>
<erected_equipment_list>
<equipment_code>S1309</equipment_code>
<erected_qnty>356</erected_qnty>
</erected_equipment_list>
<site_code>2E1012</site_code>
<erected_equipment_list>
<equipment_code>S215</equipment_code>
<erected_qnty>806</erected_qnty>
</erected_equipment_list>
</ns1:site_equipment>
which has <site_code>2E1012</site_code> replicated more than once.
(3) Also have tried this, but came up with a total disaster:
WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema-instance' AS xsi,
'http://www.w3.org/2001/XMLSchema' AS xsd,
'ns0:cape_site' AS ns1)
SELECT jc.WBSNumber "site_code",
(SELECT
jst.EquipmentNo "equipment_code",
SUM(jst.Qty) "erected_qnty"
FROM Job_Stock_Tbl jst
WHERE jc.CapeId = jst.CapeId
FOR XML PATH('erected_equipment_list'),TYPE)
FROM Job_Card jc
--group by jc.WBSNumber
FOR XML PATH(''), ROOT ('ns1:site_equipment');
Please advise.
Thanks in advance!
July 12, 2011 at 6:16 am
Can you post the DDL and DML to create the sample data.
____________________________________________________
Deja View - The strange feeling that somewhere, sometime you've optimised this query before
How to get the best help on a forum
http://www.sqlservercentral.com/articles/Best+Practices/61537July 12, 2011 at 6:25 am
Apologies,
please find below:
CREATE TABLE Job_Stock_Tbl
(
CapeId INT NULL,
EquipmentNo VARCHAR(15) NULL,
Qty INT NULL
);
GO
CREATE TABLE Job_Card
(
CapeId INT NOT NULL,
WBSNumber VARCHAR(15) NULL
);
GO
INSERT INTO Job_Card
VALUES (1,'2E1012');
INSERT INTO Job_Stock_Tbl
VALUES (1,'S1307',2);
INSERT INTO Job_Stock_Tbl
VALUES (1,'S1308',3);
INSERT INTO Job_Stock_Tbl
VALUES (1,'S1309',5);
July 12, 2011 at 6:49 am
I'm not sure if you can do this without generating extra namespace definitions, there's a Connect item for it here
WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema-instance' AS xsi,
'http://www.w3.org/2001/XMLSchema' AS xsd,
'ns0:cape_site' AS ns1)
SELECT jc.WBSNumber AS "site_code",
(SELECT jst.EquipmentNo "equipment_code",
jst.Qty "erected_qnty"
FROM Job_Stock_Tbl jst
WHERE jc.CapeId = jst.CapeId
FOR XML PATH('erected_equipment_list'),TYPE
)
FROM Job_Card jc
FOR XML PATH('ns1:site_equipment'),TYPE;
____________________________________________________
Deja View - The strange feeling that somewhere, sometime you've optimised this query before
How to get the best help on a forum
http://www.sqlservercentral.com/articles/Best+Practices/61537July 12, 2011 at 6:54 am
Let's omit XMLNAMESPACES for a moment,
How would you update my code to extract the site_code element only once, please?
Thanks
July 12, 2011 at 6:57 am
This is the query from above without the WITH XMLNAMESPACES clause
SELECT jc.WBSNumber AS "site_code",
(SELECT jst.EquipmentNo "equipment_code",
jst.Qty "erected_qnty"
FROM Job_Stock_Tbl jst
WHERE jc.CapeId = jst.CapeId
FOR XML PATH('erected_equipment_list'),TYPE
)
FROM Job_Card jc
FOR XML PATH('site_equipment'),TYPE;
____________________________________________________
Deja View - The strange feeling that somewhere, sometime you've optimised this query before
How to get the best help on a forum
http://www.sqlservercentral.com/articles/Best+Practices/61537July 12, 2011 at 8:09 am
Thanks
July 12, 2011 at 9:37 am
SOLVED IT!
THANKS FOR THE IDEAS!
DECLARE @xml_body xml;
SET @xml_body = (
SELECT jst.EquipmentNo "erected_equipment_list/equipment_code",
SUM(jst.Qty) "erected_equipment_list/erected_qnty"
FROM Job_Stock_Tbl jst
JOIN Job_Card job
ON job.CapeId = jst.CapeId
WHERE jst.EquipmentNo IN ('S215','S1307','S1308','S1309')
and job.WBSNumber = '2E1012'
GROUP BY job.WBSNumber,
jst.EquipmentNo
FOR XML PATH(''),type);
WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema-instance' AS xsi,
'http://www.w3.org/2001/XMLSchema' AS xsd,
'ns0:cape_site' AS ns1)
SELECT '2E1012' "site_code",
@xml_body
FOR XML PATH(''),ROOT ('ns1:site_equipment');
July 12, 2011 at 9:50 am
Great, here's another way
WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema-instance' AS xsi,
'http://www.w3.org/2001/XMLSchema' AS xsd,
'ns0:cape_site' AS ns1),
OrderedData AS (
SELECT jc.WBSNumber,
jst.EquipmentNo,
jst.Qty,
ROW_NUMBER() OVER(PARTITION BY jc.WBSNumber ORDER BY jst.EquipmentNo) AS rn
FROM Job_Card jc
INNER JOIN Job_Stock_Tbl jst ON jc.CapeId = jst.CapeId
)
SELECT CASE WHEN rn=1 THEN WBSNumber END AS "site_code",
EquipmentNo AS "erected_equipment_list/equipment_code",
Qty AS "erected_equipment_list/erected_qnty"
FROM OrderedData
FOR XML PATH(''),ROOT('ns1:site_equipment'),TYPE;
____________________________________________________
Deja View - The strange feeling that somewhere, sometime you've optimised this query before
How to get the best help on a forum
http://www.sqlservercentral.com/articles/Best+Practices/61537July 12, 2011 at 9:56 am
OK,
First you won - yours looks better 😀 . Thx
Second - I was too excited: How do I add <?xml version="1.0" encoding="ISO-8859-1" standalone="no" ?>
for the happy end?
THX!
July 12, 2011 at 10:03 am
As far as I know, the only workaround is to convert the XML to the varchar(max) type and then prepend the header
SELECT '<?xml version="1.0" encoding="ISO-8859-1" ?>'
+
CAST( (SELECT ... FOR XML PATH...) ) AS VARCHAR(MAX))
____________________________________________________
Deja View - The strange feeling that somewhere, sometime you've optimised this query before
How to get the best help on a forum
http://www.sqlservercentral.com/articles/Best+Practices/61537July 12, 2011 at 10:29 am
This is what I thought as well, but didn't want to convert it to VARCHAR.
Again, thanks for the help.
July 14, 2011 at 2:03 am
Mark,
now to the most stupid question, please:
How do I assign the result to a variable, i.e. how do I write something like this that will also work 😀
DECLARE @xml_result xml;
@xml_result = WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema-instance' AS xsi,
'http://www.w3.org/2001/XMLSchema' AS xsd,
'ns0:cape_site' AS ns1),
OrderedData AS (
SELECT jc.WBSNumber,
jst.EquipmentNo,
SUM(jst.Qty) as Qty,
ROW_NUMBER() OVER(PARTITION BY jc.WBSNumber ORDER BY jst.EquipmentNo) AS rn
FROM Job_Card jc
JOIN Job_Stock_Tbl jst
ON jc.CapeId = jst.CapeId
GROUP BY jc.WBSNumber,
jst.EquipmentNo
)
SELECT CASE WHEN rn=1 THEN WBSNumber END AS "site_code",
EquipmentNo AS "erected_equipment_list/equipment_code",
Qty AS "erected_equipment_list/erected_qnty"
FROM OrderedData
FOR XML PATH(''),ROOT('ns1:site_equipment'),TYPE;
Thanks!
July 14, 2011 at 2:05 am
DECLARE @xml_result XML;
WITH XMLNAMESPACES('http://www.w3.org/2001/XMLSchema-instance' AS xsi,
'http://www.w3.org/2001/XMLSchema' AS xsd,
'ns0:cape_site' AS ns1),
OrderedData AS (
SELECT jc.WBSNumber,
jst.EquipmentNo,
SUM(jst.Qty) as Qty,
ROW_NUMBER() OVER(PARTITION BY jc.WBSNumber ORDER BY jst.EquipmentNo) AS rn
FROM Job_Card jc
JOIN Job_Stock_Tbl jst
ON jc.CapeId = jst.CapeId
GROUP BY jc.WBSNumber,
jst.EquipmentNo
)
SELECT @xml_result = (
SELECT CASE WHEN rn=1 THEN WBSNumber END AS "site_code",
EquipmentNo AS "erected_equipment_list/equipment_code",
Qty AS "erected_equipment_list/erected_qnty"
FROM OrderedData
FOR XML PATH(''),ROOT('ns1:site_equipment'),TYPE);
____________________________________________________
Deja View - The strange feeling that somewhere, sometime you've optimised this query before
How to get the best help on a forum
http://www.sqlservercentral.com/articles/Best+Practices/61537July 14, 2011 at 2:07 am
Oh boy.....:blush:
Viewing 15 posts - 1 through 14 (of 14 total)
You must be logged in to reply to this topic. Login to reply