1

I have sample xml data with address. It works well but there's one problem. I use "/" to concatenate house number and flat number but if there's no flat number I receive something like that: 1 /.

Here's my example:

declare @xml as xml = '<root>
                    <Row>
                            <proceeding>
                                    <signatures>V GU 86/18</signatures>
                                    <signatures>V GUp 9/19</signatures>
                                    <signatures>V GUp 8/19</signatures>
                            </proceeding>
                            <entity>
                                    <info>
                                            <cleaned_name>Kate Smith</cleaned_name>
                                    </info>
                                    <address>
                                            <town>London </town>
                                            <house_number>1 </house_number>
                                            <flat_number>1</flat_number>
                                            <street>Downing Street</street>
                                            <zip_code>00-001</zip_code>
                                    </address>
                                    <address>
                                            <town>Yorkshire </town>
                                            <house_number>1 </house_number>
                                            <flat_number>1</flat_number>
                                            <street>Morning Street</street>
                                            <zip_code>00-999</zip_code>
                                    </address>
                            </entity>
                            <entity>
                                    <info>
                                            <cleaned_name>John Smith</cleaned_name>
                                    </info>
                                    <address>
                                            <town>Washington </town>
                                            <house_number>1</house_number>
                                            <flat_number>1</flat_number>
                                            <street>Pennsylvania Avenue</street>
                                            <zip_code>00-001</zip_code>
                                    </address>
                                    <address>
                                            <town>Washington </town>
                                            <house_number>1</house_number>
                                            <flat_number></flat_number>
                                            <street>Pennsylvania Avenue</street>
                                            <zip_code>00-001</zip_code>
                                    </address>
                            </entity>
                    </Row>
            </root>'


            select 
             isnull(STUFF(a.x.query('for $s in  entity/info/cleaned_name return <x>{concat(",",$s)}</x>').value('.','varchar(max)'),1,1,''),'') as 'Nazwa podmiotu' 
            ,isnull(STUFF(a.x.query('for $s in proceeding/signatures return <x>{concat(",",$s)}</x>').value('.','varchar(max)'),1,1,''),'') as 'Sygnatura'
            ,isnull(STUFF(a.x.query('for $s in entity/address
                        return
                        <x>{concat(", ",($s/zip_code/text())[1]," "
                                       ,($s/town/text())[1]," "
                                       ,($s/street/text())[1]," "
                                       ,($s/house_number/text())[1],"/"
                                       ,($s/flat_number/text())[1]
                                   )}</x>')
               .query('for $a in distinct-values(/x/text()) return $a').value('.','varchar(max)'),1,2,''),'')  
from @xml.nodes('/root/Row') as a(x);

This is what I get: enter image description here

And that's my desired outcome: xml

Here's what I've tried so far:

declare @v varchar(20)='house_number'

            select 
            isnull(STUFF(a.x.query('for $s in  entity/info/cleaned_name return <x>{concat(",",$s)}</x>').value('.','varchar(max)'),1,1,''),'') as 'Nazwa podmiotu' 
            ,isnull(STUFF(a.x.query('for $s in proceeding/signatures return <x>{concat(",",$s)}</x>').value('.','varchar(max)'),1,1,''),'') as 'Sygnatura'
            ,isnull(STUFF(a.x.query('if (sql:variable("@v")="") then for $s in entity/address
            return
            <x>{concat(", ",($s/zip_code/text())[1]," "
            ,($s/town/text())[1]," "
            ,($s/street/text())[1]," "
            ,($s/house_number/text())[1]
            )}</x>
            else                     
            <x>{concat(", ",($s/zip_code/text())[1]," "
            ,($s/town/text())[1]," "
            ,($s/street/text())[1]," "
            ,($s/house_number/text())[1],"/"
            ,($s/flat_number/text())[1]
            )}</x>          
            ')                                              
            .query('for $a in distinct-values(/x/text()) return $a').value('.','varchar(max)'),1,2,''),'') 
            from @xml.nodes('/root/Row') as a(x);

I receive the following error: XQuery [query()]: The variable '$s' was not found in the scope in which it was referenced. I'm wondering if I can achieve my goal in that way.

3 Answers 3

1

I'm not quite sure what problem the other answers are solving, but for the question as described in the title, you can replace

($s/house_number/text())[1],"/",($s/flat_number/text())[1]

in the concat params with

string-join((($s/house_number/text())[1], ($s/flat_number/text())[1]), '/')

which will insert the "/" only if both house-number and flat-number exist.

I can't see why the [1] subscripts are needed (perhaps to defeat static type-checking?) but I've left them in.

Sign up to request clarification or add additional context in comments.

2 Comments

string-join() is not supported in SQL Server's very reduced XQuery engine. But it's a clever idea :-) And about the [1]: SQL Server demands for a singleton in concat()...
@Arkadiusz, please go ahead and up-vote elevation of SQL Server XML functionality to match latest w3c standards: feedback.azure.com/forums/908035-sql-server/suggestions/…
0

I've done it other way and it works.

            select 
             isnull(STUFF(a.x.query('for $s in  entity/info/cleaned_name return <x>{concat(",",$s)}</x>').value('.','varchar(max)'),1,1,''),'') as 'Nazwa podmiotu' 
            ,isnull(STUFF(a.x.query('for $s in proceeding/signatures return <x>{concat(",",$s)}</x>').value('.','varchar(max)'),1,1,''),'') as 'Sygnatura'
            ,isnull(STUFF(a.x.query('for $s in entity/address
                        return

                                                    if ($s/flat_number="")
                                                    then
                        <x>{concat(", ",($s/zip_code/text())[1]," "
                                       ,($s/town/text())[1]," "
                                       ,($s/street/text())[1]," "
                                       ,($s/house_number/text())[1]
                                   )}</x>

                                                    else
                                                    <x>{concat(", ",($s/zip_code/text())[1]," "
                                                                            ,($s/town/text())[1]," "
                                                                            ,($s/street/text())[1]," "
                                                                            ,($s/house_number/text())[1],"/"
                                                                            ,($s/flat_number/text())[1]
                                                                            )}</x>       
                                                    ')
               .query('for $a in distinct-values(/x/text()) return $a').value('.','varchar(max)'),1,2,''),'')  
from @xml.nodes('/root/Row') as a(x);

Comments

0

Well, in this case your last question's title (which I've changed in the meanwhile) "How to use LET" might have a revival :-)

Try this:

select 
    isnull(STUFF(a.x.query('for $s in  entity/info/cleaned_name return <x>{concat(",",$s)}</x>').value('.','varchar(max)'),1,1,''),'') as 'Nazwa podmiotu' 
,isnull(STUFF(a.x.query('for $s in proceeding/signatures return <x>{concat(",",$s)}</x>').value('.','varchar(max)'),1,1,''),'') as 'Sygnatura'
,isnull(STUFF(a.x.query('for $s in entity/address
            let $houseFlat:=if($s/flat_number/text()) 
                            then concat(($s/house_number/text())[1],"/",($s/flat_number/text())[1])
                            else string(($s/house_number/text())[1])
            return
            <x>{concat(", ",($s/zip_code/text())[1]," "
                            ,($s/town/text())[1]," "
                            ,($s/street/text())[1]," "
                            ,$houseFlat
                        )}</x>')
    .query('for $a in distinct-values(/x/text()) return $a').value('.','varchar(max)'),1,2,''),'')  
from @xml.nodes('/root/Row') as a(x);

But - at least in this case - distinct-values() will not help. The both addresses are not identical due to 1 and 1/1 in the house and street number...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.