Reputation: 380
I have a table with an XML
data type column called Settings
. The structure of the XML
data:
<root>
<Setting1>true</Setting1>
<Setting2>false</Setting2>
...
<root>
The table also has an ID
column that I would like to use to group my results. I want to count how many Setting1
configurations are set to true
per ID
. Note: The ID
field is not unique and can repeat.
Here is what I have so far:
with xmlnamespaces (DEFAULT '...')
select count(Setting1) as counts
from (select Settings.value('(/root/Setting1)[1]', 'nvarchar(max)') as Setting1
from MY_TABLE
group by ID) res
where Setting1= 'true'
However I am getting the following error:
Column 'MY_TABLE.Configuration' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
Upvotes: 2
Views: 256
Reputation: 67291
Although you've got an answer already, I'd like to add some alternatives:
(Credits to Michal Turczyn for the mockup)
declare @tbl table (id int, xmlCol xml);
insert into @tbl values
(1, '<root>
<Setting1>true</Setting1>
<Setting2>false</Setting2>
</root>'),
(1, '<root>
<Setting1>true</Setting1>
<Setting2>false</Setting2>
</root>'),
(2, '<root>
<Setting1>false</Setting1>
<Setting2>false</Setting2>
</root>'),
(2, '<root>
<Setting1>true</Setting1>
<Setting2>false</Setting2>
</root>');
The fastest should be a simple XML.exist()
:
SELECT t.id,
sum(CASE WHEN t.xmlCol.exist('/root/Setting1[text()="true"]')=1 THEN 1 ELSE 0 END) howManyTrue
FROM @tbl t
GROUP BY t.id
You can enhance this with a variable to set the SettingName outside the statement:
DECLARE @SettingName NVARCHAR(100)=N'Setting1';
SELECT t.id,
sum(CASE WHEN t.xmlCol.exist('/root/*[local-name()=sql:variable("@SettingName") and text()="true"]')=1 THEN 1 ELSE 0 END) howManyTrue
FROM @tbl t
GROUP BY t.id
--And if a Setting might occur more than once within one XML, you might use XQuery's count()
:
SELECT t.id,
sum(t.xmlCol.value('count(/root/*[local-name()=sql:variable("@SettingName") and text()="true"])','int')) howManyTrue
FROM @tbl t
GROUP BY t.id
Upvotes: 1
Reputation: 37337
Try this query:
declare @tbl table (id int, xmlCol xml);
insert into @tbl values
(1, '<root>
<Setting1>true</Setting1>
<Setting2>false</Setting2>
</root>'),
(1, '<root>
<Setting1>true</Setting1>
<Setting2>false</Setting2>
</root>'),
(2, '<root>
<Setting1>false</Setting1>
<Setting2>false</Setting2>
</root>'),
(2, '<root>
<Setting1>true</Setting1>
<Setting2>false</Setting2>
</root>');
select id,
sum(convert(int, xmlCol.value('(/root//Setting1/node())[1]', 'bit'))) howManyTrue
from @tbl
group by id
Upvotes: 1