Welcome to dbFreaks.com!
FAQFAQ    SearchSearch      ProfileProfile    Private MessagesPrivate Messages   Log inLog in

Inner Query Coalesce Causes Incorrect Query Results?

 
   Database Help (Home) -> Server RSS
Next:  FM 11 server and web?  
Author Message
Keith Steele

External


Since: Mar 19, 2010
Posts: 1



(Msg. 1) Posted: Fri Mar 19, 2010 11:19 am
Post subject: Inner Query Coalesce Causes Incorrect Query Results?
Archived from groups: microsoft>public>sqlserver>server (more info?)

We have come across a peculiar situation where we get some very different
behaviour when an inner query contains a coalesce. We are flattening out a
list into a comma separated string variable. The desired goal is to have a
comma separated list of people in alphabetical order.

People are stored in table #tblA and their names can optionally be
overridden in #tblB in a 1-to-1 relationship. We are aggregating the names
in an outer query that appends to a local variable.

Below is the code illustrating 4 different scenarios, none of which fully
work. This code can be pasted directly into a SQL Server 2005 or SQL Server
2008 query window and executed without any setup.

The ResultFailed column should have returned 3 items, however it only
returns 1. This is the code that makes most sense and should work. The
ResultsSuccess column returns the correct results, however it is not
guaranteed to be in alphabetical order (we removed the order by clause). The
ResultsSuccessGroupBy column does return required results, however there is a
Group By clause in the outer query that shouldn't be necessary (there are no
aggregate functions involved). The ResultsSuccessNoInnerCoalesce column
shows the correct number of items in the list, however it is missing the
overrides provided by the inner coalesce.

Please review and let us know what is wrong with the code. In our opinion,
this appears to be a bug in the way SQL Server is executing this query.

Thanks,
Keith


if object_id('tempdb.dbo.#tblA') is not null drop table #tblA
create table #tblA (PersonID int not null, FullName varchar(25) not null)

insert into #tblA(PersonID, FullName)
select 1, 'Person1' union select 2, 'Person2'

if object_id('tempdb.dbo.#tblB') is not null drop table #tblB
create table #tblB (PersonID int not null, FullName varchar(25) null)

insert into #tblB(PersonID, FullName)
select 1, null union select 2, 'Person2 override' union select 3, 'Person3
override'


declare @flattenFails varchar(max)
declare @flattenWorksButNotOrdered varchar(max)
declare @flattenWorksWithGroupBy varchar(max)
declare @flattenWorksNoInnerCoalesce varchar(max)

select @flattenWorksButNotOrdered = coalesce(@flattenWorksButNotOrdered + ',
', '') + x.FullName
from (
select #tblB.PersonID, coalesce(#tblB.FullName, #tblA.FullName) as
FullName
from #tblB left join #tblA on #tblB.PersonID = #tblA.PersonID
) x
--order by x.FullName

select @flattenWorksWithGroupBy = coalesce(@flattenWorksWithGroupBy + ', ',
'') + x.FullName
from (
select #tblB.PersonID, coalesce(#tblB.FullName, #tblA.FullName) as
FullName
from #tblB left join #tblA on #tblB.PersonID = #tblA.PersonID
) x
group by x.FullName
order by x.FullName

select @flattenWorksNoInnerCoalesce = coalesce(@flattenWorksNoInnerCoalesce
+ ', ', '') + x.FullName
from (
select #tblB.PersonID, #tblB.FullName as FullName
from #tblB left join #tblA on #tblB.PersonID = #tblA.PersonID
) x
order by x.FullName

select @flattenFails = coalesce(@flattenFails + ', ', '') + x.FullName
from (
select #tblB.PersonID, coalesce(#tblB.FullName, #tblA.FullName) as
FullName
from #tblB left join #tblA on #tblB.PersonID = #tblA.PersonID
) x
order by x.FullName

select @flattenFails as ResultFailed, @flattenWorksButNotOrdered as
ResultSuccessNotOrdered, @flattenWorksWithGroupBy as ResultsSuccessGroupBy,
@flattenWorksNoInnerCoalesce as ResultsSuccessNoInnerCoalesce

drop table #tblA
drop table #tblB

 >> Stay informed about: Inner Query Coalesce Causes Incorrect Query Results? 
Back to top
Login to vote
Gert-Jan Strik

External


Since: Feb 19, 2010
Posts: 6



(Msg. 2) Posted: Fri Mar 19, 2010 4:25 pm
Post subject: Re: Inner Query Coalesce Causes Incorrect Query Results? [Login to view extended thread Info.]
Archived from groups: per prev. post (more info?)

Keith,

What it boils down to, is that you are currently using this:

select @flattenFails = coalesce(@flattenFails + ', ', '') + x.FullName
from ...

The problem is, that for multirow selections, the value of the variable
is undefined. And even if it returns a concatenated list of strings,
then you don't get to determine the order of the items. So it is
impossible to guarantee alphabetical order using this method.

There are many possible solutions, but using the "FOR XML" method is
probably easiest. See URL below (may wrap)

http://groups.google.nl/group/comp.databases.ms-sqlserver/browse_threa...hread/f

--
Gert-Jan



Keith Steele wrote:
>
> We have come across a peculiar situation where we get some very different
> behaviour when an inner query contains a coalesce. We are flattening out a
> list into a comma separated string variable. The desired goal is to have a
> comma separated list of people in alphabetical order.
>
> People are stored in table #tblA and their names can optionally be
> overridden in #tblB in a 1-to-1 relationship. We are aggregating the names
> in an outer query that appends to a local variable.
>
> Below is the code illustrating 4 different scenarios, none of which fully
> work. This code can be pasted directly into a SQL Server 2005 or SQL Server
> 2008 query window and executed without any setup.
>
> The ResultFailed column should have returned 3 items, however it only
> returns 1. This is the code that makes most sense and should work. The
> ResultsSuccess column returns the correct results, however it is not
> guaranteed to be in alphabetical order (we removed the order by clause). The
> ResultsSuccessGroupBy column does return required results, however there is a
> Group By clause in the outer query that shouldn't be necessary (there are no
> aggregate functions involved). The ResultsSuccessNoInnerCoalesce column
> shows the correct number of items in the list, however it is missing the
> overrides provided by the inner coalesce.
>
> Please review and let us know what is wrong with the code. In our opinion,
> this appears to be a bug in the way SQL Server is executing this query.
>
> Thanks,
> Keith
>
> if object_id('tempdb.dbo.#tblA') is not null drop table #tblA
> create table #tblA (PersonID int not null, FullName varchar(25) not null)
>
> insert into #tblA(PersonID, FullName)
> select 1, 'Person1' union select 2, 'Person2'
>
> if object_id('tempdb.dbo.#tblB') is not null drop table #tblB
> create table #tblB (PersonID int not null, FullName varchar(25) null)
>
> insert into #tblB(PersonID, FullName)
> select 1, null union select 2, 'Person2 override' union select 3, 'Person3
> override'
>
> declare @flattenFails varchar(max)
> declare @flattenWorksButNotOrdered varchar(max)
> declare @flattenWorksWithGroupBy varchar(max)
> declare @flattenWorksNoInnerCoalesce varchar(max)
>
> select @flattenWorksButNotOrdered = coalesce(@flattenWorksButNotOrdered + ',
> ', '') + x.FullName
> from (
> select #tblB.PersonID, coalesce(#tblB.FullName, #tblA.FullName) as
> FullName
> from #tblB left join #tblA on #tblB.PersonID = #tblA.PersonID
> ) x
> --order by x.FullName
>
> select @flattenWorksWithGroupBy = coalesce(@flattenWorksWithGroupBy + ', ',
> '') + x.FullName
> from (
> select #tblB.PersonID, coalesce(#tblB.FullName, #tblA.FullName) as
> FullName
> from #tblB left join #tblA on #tblB.PersonID = #tblA.PersonID
> ) x
> group by x.FullName
> order by x.FullName
>
> select @flattenWorksNoInnerCoalesce = coalesce(@flattenWorksNoInnerCoalesce
> + ', ', '') + x.FullName
> from (
> select #tblB.PersonID, #tblB.FullName as FullName
> from #tblB left join #tblA on #tblB.PersonID = #tblA.PersonID
> ) x
> order by x.FullName
>
> select @flattenFails = coalesce(@flattenFails + ', ', '') + x.FullName
> from (
> select #tblB.PersonID, coalesce(#tblB.FullName, #tblA.FullName) as
> FullName
> from #tblB left join #tblA on #tblB.PersonID = #tblA.PersonID
> ) x
> order by x.FullName
>
> select @flattenFails as ResultFailed, @flattenWorksButNotOrdered as
> ResultSuccessNotOrdered, @flattenWorksWithGroupBy as ResultsSuccessGroupBy,
> @flattenWorksNoInnerCoalesce as ResultsSuccessNoInnerCoalesce
>
> drop table #tblA
> drop table #tblB

 >> Stay informed about: Inner Query Coalesce Causes Incorrect Query Results? 
Back to top
Login to vote
Keith Steele

External


Since: Mar 26, 2010
Posts: 1



(Msg. 3) Posted: Fri Mar 26, 2010 12:24 pm
Post subject: Re: Inner Query Coalesce Causes Incorrect Query Results? [Login to view extended thread Info.]
Archived from groups: per prev. post (more info?)

While that may be the case (in that we can't determine order of the string
list), it does not explain why having a coalesce in the inner query
completely changes the behaviour of the outer query. To me, this is very
dangerous - imagine if the inner query was a view. You'd expect that, no
matter what query the view uses, the outer results would stay consistent.
But in this case, adding a simple coalesce to the view (the inner query) can
completely mess up your query in an unexpected fashion.

Keith

"Gert-Jan Strik" wrote:

> Keith,
>
> What it boils down to, is that you are currently using this:
>
> select @flattenFails = coalesce(@flattenFails + ', ', '') + x.FullName
> from ...
>
> The problem is, that for multirow selections, the value of the variable
> is undefined. And even if it returns a concatenated list of strings,
> then you don't get to determine the order of the items. So it is
> impossible to guarantee alphabetical order using this method.
>
> There are many possible solutions, but using the "FOR XML" method is
> probably easiest. See URL below (may wrap)
>
> http://groups.google.nl/group/comp.databases.ms-sqlserver/browse_threa...hread/f
>
> --
> Gert-Jan
>
>
>
> Keith Steele wrote:
> >
> > We have come across a peculiar situation where we get some very different
> > behaviour when an inner query contains a coalesce. We are flattening out a
> > list into a comma separated string variable. The desired goal is to have a
> > comma separated list of people in alphabetical order.
> >
> > People are stored in table #tblA and their names can optionally be
> > overridden in #tblB in a 1-to-1 relationship. We are aggregating the names
> > in an outer query that appends to a local variable.
> >
> > Below is the code illustrating 4 different scenarios, none of which fully
> > work. This code can be pasted directly into a SQL Server 2005 or SQL Server
> > 2008 query window and executed without any setup.
> >
> > The ResultFailed column should have returned 3 items, however it only
> > returns 1. This is the code that makes most sense and should work. The
> > ResultsSuccess column returns the correct results, however it is not
> > guaranteed to be in alphabetical order (we removed the order by clause). The
> > ResultsSuccessGroupBy column does return required results, however there is a
> > Group By clause in the outer query that shouldn't be necessary (there are no
> > aggregate functions involved). The ResultsSuccessNoInnerCoalesce column
> > shows the correct number of items in the list, however it is missing the
> > overrides provided by the inner coalesce.
> >
> > Please review and let us know what is wrong with the code. In our opinion,
> > this appears to be a bug in the way SQL Server is executing this query.
> >
> > Thanks,
> > Keith
> >
> > if object_id('tempdb.dbo.#tblA') is not null drop table #tblA
> > create table #tblA (PersonID int not null, FullName varchar(25) not null)
> >
> > insert into #tblA(PersonID, FullName)
> > select 1, 'Person1' union select 2, 'Person2'
> >
> > if object_id('tempdb.dbo.#tblB') is not null drop table #tblB
> > create table #tblB (PersonID int not null, FullName varchar(25) null)
> >
> > insert into #tblB(PersonID, FullName)
> > select 1, null union select 2, 'Person2 override' union select 3, 'Person3
> > override'
> >
> > declare @flattenFails varchar(max)
> > declare @flattenWorksButNotOrdered varchar(max)
> > declare @flattenWorksWithGroupBy varchar(max)
> > declare @flattenWorksNoInnerCoalesce varchar(max)
> >
> > select @flattenWorksButNotOrdered = coalesce(@flattenWorksButNotOrdered + ',
> > ', '') + x.FullName
> > from (
> > select #tblB.PersonID, coalesce(#tblB.FullName, #tblA.FullName) as
> > FullName
> > from #tblB left join #tblA on #tblB.PersonID = #tblA.PersonID
> > ) x
> > --order by x.FullName
> >
> > select @flattenWorksWithGroupBy = coalesce(@flattenWorksWithGroupBy + ', ',
> > '') + x.FullName
> > from (
> > select #tblB.PersonID, coalesce(#tblB.FullName, #tblA.FullName) as
> > FullName
> > from #tblB left join #tblA on #tblB.PersonID = #tblA.PersonID
> > ) x
> > group by x.FullName
> > order by x.FullName
> >
> > select @flattenWorksNoInnerCoalesce = coalesce(@flattenWorksNoInnerCoalesce
> > + ', ', '') + x.FullName
> > from (
> > select #tblB.PersonID, #tblB.FullName as FullName
> > from #tblB left join #tblA on #tblB.PersonID = #tblA.PersonID
> > ) x
> > order by x.FullName
> >
> > select @flattenFails = coalesce(@flattenFails + ', ', '') + x.FullName
> > from (
> > select #tblB.PersonID, coalesce(#tblB.FullName, #tblA.FullName) as
> > FullName
> > from #tblB left join #tblA on #tblB.PersonID = #tblA.PersonID
> > ) x
> > order by x.FullName
> >
> > select @flattenFails as ResultFailed, @flattenWorksButNotOrdered as
> > ResultSuccessNotOrdered, @flattenWorksWithGroupBy as ResultsSuccessGroupBy,
> > @flattenWorksNoInnerCoalesce as ResultsSuccessNoInnerCoalesce
> >
> > drop table #tblA
> > drop table #tblB
> .
>
 >> Stay informed about: Inner Query Coalesce Causes Incorrect Query Results? 
Back to top
Login to vote
Gert-Jan Strik

External


Since: Feb 19, 2010
Posts: 6



(Msg. 4) Posted: Fri Mar 26, 2010 4:25 pm
Post subject: Re: Inner Query Coalesce Causes Incorrect Query Results? [Login to view extended thread Info.]
Archived from groups: per prev. post (more info?)

Maybe you should re-read my response, especially the first line that
says "undefined". With that classification, all bets are off. In my
opinion, SQL Server should thow an error whenever multiple values are
assigned to a local variable. However, this is not the implemented
behavior. Instead, the local variable will get "some" value.

The fact that in your case, a change in behavior was triggered when you
changed the inner query, that proves the point. The change doesn't mess
up your query, because your query was already messed up.

So you are completely right: it is very dangerous to use expressions
that have undefined behavior. Therefore the advice to avoid it.

--
Gert-Jan


Keith Steele wrote:
>
> While that may be the case (in that we can't determine order of the string
> list), it does not explain why having a coalesce in the inner query
> completely changes the behaviour of the outer query. To me, this is very
> dangerous - imagine if the inner query was a view. You'd expect that, no
> matter what query the view uses, the outer results would stay consistent.
> But in this case, adding a simple coalesce to the view (the inner query) can
> completely mess up your query in an unexpected fashion.
>
> Keith
>
> "Gert-Jan Strik" wrote:
>
> > Keith,
> >
> > What it boils down to, is that you are currently using this:
> >
> > select @flattenFails = coalesce(@flattenFails + ', ', '') + x.FullName
> > from ...
> >
> > The problem is, that for multirow selections, the value of the variable
> > is undefined. And even if it returns a concatenated list of strings,
> > then you don't get to determine the order of the items. So it is
> > impossible to guarantee alphabetical order using this method.
> >
> > There are many possible solutions, but using the "FOR XML" method is
> > probably easiest. See URL below (may wrap)
> >
> > http://groups.google.nl/group/comp.databases.ms-sqlserver/browse_threa...hread/f
> >
> > --
> > Gert-Jan
> >
> >
> >
> > Keith Steele wrote:
> > >
> > > We have come across a peculiar situation where we get some very different
> > > behaviour when an inner query contains a coalesce. We are flattening out a
> > > list into a comma separated string variable. The desired goal is to have a
> > > comma separated list of people in alphabetical order.
> > >
> > > People are stored in table #tblA and their names can optionally be
> > > overridden in #tblB in a 1-to-1 relationship. We are aggregating the names
> > > in an outer query that appends to a local variable.
> > >
> > > Below is the code illustrating 4 different scenarios, none of which fully
> > > work. This code can be pasted directly into a SQL Server 2005 or SQL Server
> > > 2008 query window and executed without any setup.
> > >
> > > The ResultFailed column should have returned 3 items, however it only
> > > returns 1. This is the code that makes most sense and should work. The
> > > ResultsSuccess column returns the correct results, however it is not
> > > guaranteed to be in alphabetical order (we removed the order by clause). The
> > > ResultsSuccessGroupBy column does return required results, however there is a
> > > Group By clause in the outer query that shouldn't be necessary (there are no
> > > aggregate functions involved). The ResultsSuccessNoInnerCoalesce column
> > > shows the correct number of items in the list, however it is missing the
> > > overrides provided by the inner coalesce.
> > >
> > > Please review and let us know what is wrong with the code. In our opinion,
> > > this appears to be a bug in the way SQL Server is executing this query.
> > >
> > > Thanks,
> > > Keith
> > >
> > > if object_id('tempdb.dbo.#tblA') is not null drop table #tblA
> > > create table #tblA (PersonID int not null, FullName varchar(25) not null)
> > >
> > > insert into #tblA(PersonID, FullName)
> > > select 1, 'Person1' union select 2, 'Person2'
> > >
> > > if object_id('tempdb.dbo.#tblB') is not null drop table #tblB
> > > create table #tblB (PersonID int not null, FullName varchar(25) null)
> > >
> > > insert into #tblB(PersonID, FullName)
> > > select 1, null union select 2, 'Person2 override' union select 3, 'Person3
> > > override'
> > >
> > > declare @flattenFails varchar(max)
> > > declare @flattenWorksButNotOrdered varchar(max)
> > > declare @flattenWorksWithGroupBy varchar(max)
> > > declare @flattenWorksNoInnerCoalesce varchar(max)
> > >
> > > select @flattenWorksButNotOrdered = coalesce(@flattenWorksButNotOrdered + ',
> > > ', '') + x.FullName
> > > from (
> > > select #tblB.PersonID, coalesce(#tblB.FullName, #tblA.FullName) as
> > > FullName
> > > from #tblB left join #tblA on #tblB.PersonID = #tblA.PersonID
> > > ) x
> > > --order by x.FullName
> > >
> > > select @flattenWorksWithGroupBy = coalesce(@flattenWorksWithGroupBy + ', ',
> > > '') + x.FullName
> > > from (
> > > select #tblB.PersonID, coalesce(#tblB.FullName, #tblA.FullName) as
> > > FullName
> > > from #tblB left join #tblA on #tblB.PersonID = #tblA.PersonID
> > > ) x
> > > group by x.FullName
> > > order by x.FullName
> > >
> > > select @flattenWorksNoInnerCoalesce = coalesce(@flattenWorksNoInnerCoalesce
> > > + ', ', '') + x.FullName
> > > from (
> > > select #tblB.PersonID, #tblB.FullName as FullName
> > > from #tblB left join #tblA on #tblB.PersonID = #tblA.PersonID
> > > ) x
> > > order by x.FullName
> > >
> > > select @flattenFails = coalesce(@flattenFails + ', ', '') + x.FullName
> > > from (
> > > select #tblB.PersonID, coalesce(#tblB.FullName, #tblA.FullName) as
> > > FullName
> > > from #tblB left join #tblA on #tblB.PersonID = #tblA.PersonID
> > > ) x
> > > order by x.FullName
> > >
> > > select @flattenFails as ResultFailed, @flattenWorksButNotOrdered as
> > > ResultSuccessNotOrdered, @flattenWorksWithGroupBy as ResultsSuccessGroupBy,
> > > @flattenWorksNoInnerCoalesce as ResultsSuccessNoInnerCoalesce
> > >
> > > drop table #tblA
> > > drop table #tblB
> > .
> >
 >> Stay informed about: Inner Query Coalesce Causes Incorrect Query Results? 
Back to top
Login to vote
Display posts from previous:   
Related Topics:
using XQuery to add separator to query results - I have this XML from MSDN declare @x xml set @x = ' <People> <Person> <Name>John</Name> <Age>24</Age> </Person> <Person> <Name>JGoofy</Name> <Age>34</Age> </Person> ...

query returns results even after encountering an error (li.. - I can't find anything that can refer me to a setting or direction for fixing this. Basically, I am running a query that accesses another server through a linked-server. In the script there had been a conversion issue and that became very apparent when..

compare a sub-query to an outer query to filter max sighti.. - The outer query gives me the last sighting for a rail car. Now I have the very last sighting, however within the last sighting results there will be multiple records with that clm_id(sighting) with that date but different sighting codes for different....

relate an inner query to an outer query - The outer query gives me the last sighting for a rail car. Now I have the very last sighting, however within the last sighting results there will be multiple records with that clm_id(sighting) and with that date but different sighting codes for..

convert MySQL create query to T-SQL create query -
   Database Help (Home) -> Server All times are: Pacific Time (US & Canada)
Page 1 of 1

 
You can post new topics in this forum
You can reply to topics in this forum
You can edit your posts in this forum
You can delete your posts in this forum
You can vote in polls in this forum



[ Contact us | Terms of Service/Privacy Policy ]