views:

31

answers:

2

This is a contrived example using SQL Server 2008.

I'm essentially storing a list of ids in an xml column in a table: temp (bigint id, xml ids)

I want to join the table itself to the xml nodes.

So far I have:

select * from temp x
join (
    select  x.id
    ,   ids.id.value('@value', 'bigint') zid 
    from    temp t cross apply ids.nodes('/ids/id') as ids(id)
) z on x.id=z.id

I get: The multi-part identifier "x.id" could not be bound.

This just looks like a normal correlated subquery to me. What am I missing?

----- update:

For the following sample data in the temp table:

id ids
-- ---
 1 <ids><id value="11" /><id value="12" /><id value="13" /></ids>
 2 <ids><id value="21" /><id value="22" /><id value="23" /></ids>
 3 <ids><id value="31" /><id value="32" /><id value="33" /></ids>

I would expect to see the following as the result set:

id zid
-- ---
 1  11
 1  12
 1  13
 2  21
 2  22
 2  23
 3  31
 3  32
 3  33
A: 

You are selecting x.id inside the subquery, maybe you should be selecting t.id?

despart
Thanks but no, that was intended.
enashnash
Okay, so I intended it, but it was wrong :) I've awarded the answer to Martin though, as he provided me with a more complete answer and suggested a better method to boot, but thanks for your help.
enashnash
A: 

It is a derived table not a correlated sub query. Note this doesn't work either.

WITH TEMP AS
(
SELECT 1 AS id
)

select x.id 
from temp x
join (
select  x.id,*  from temp t
) z
on  x.id  =  z.id 

From MSDN derived_table

Is a subquery that retrieves rows from the database. derived_table is used as input to the outer query.

so this is quite different to a correlated sub query where

the subquery depends on the outer query for its values. This means that the subquery is executed repeatedly, once for each row that might be selected by the outer query.

To get your expected output you don't need a JOIN at all.

WITH TEMP AS
(
select 1 as id, CAST('<ids><id value="11" /><id value="12" /><id value="13" /></ids>' as xml) as ids UNION ALL
select 2, '<ids><id value="21" /><id value="22" /><id value="23" /></ids>' UNION ALL
select 3, '<ids><id value="31" /><id value="32" /><id value="33" /></ids>'

)

 select 
 t.id,
 ids.id.value('@value', 'bigint') zid 
 from    temp t cross apply ids.nodes('/ids/id') as ids(id)

If you did decide to use one then despart's answer was correct.

select x.id, zid  from temp x
join (
    select 
    t.id,
    ids.id.value('@value', 'bigint') zid 
    from    temp t cross apply ids.nodes('/ids/id') as ids(id)
) z on x.id=z.id
Martin Smith
As far as I can see, it is a correlated subquery precisely because it depends on the outer query for its values. I'm aliasing the table 'temp' as 'x' and using it inside the join.
enashnash
@enashnash It would be a correlated subquery if that syntax was valid. But it isn't. You need to think of it as though it materialised the whole of z first then joined onto the outer query. (though probably it will be more efficient than that). Or think of the derived table as an inline View if it helps.
Martin Smith
If the whole of 'z' could be created without referencing the outer query then it wouldn't be correlated, it would just be a simple subquery, no? Or is my terminology muddled? Or if it is just my syntax which is incorrect, what should it be?I've updated the question with sample data and expected output. Given that information, could you suggest a query which would produce the expected output?
enashnash
Excellent, thanks. I'm puzzled as to why my original syntax was invalid though; I thought my intended use was part of the whole point of correlated subqueries existing in the first place!
enashnash
Because at the risk of going round in circles your syntax was **not** a correlated subquery. It was a derived table and these are different http://msdn.microsoft.com/en-us/library/ms177634.aspx
Martin Smith