Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.databases.ms-sqlserver > #1840 > unrolled thread

CASE issue

Started by"twenty-six@b-mint.net" <twenty-six@b-mint.net>
First post2014-11-24 10:22 +0000
Last post2014-11-29 10:43 +0100
Articles 14 — 5 participants

Back to article view | Back to comp.databases.ms-sqlserver


Contents

  CASE issue "twenty-six@b-mint.net" <twenty-six@b-mint.net> - 2014-11-24 10:22 +0000
    Re: CASE issue Erland Sommarskog <esquel@sommarskog.se> - 2014-11-24 11:26 +0000
      Re: CASE issue bradbury9 <ray.bradbury9@gmail.com> - 2014-11-24 04:16 -0800
        Re: CASE issue Erland Sommarskog <esquel@sommarskog.se> - 2014-11-24 14:28 +0000
          Re: CASE issue Erland Sommarskog <esquel@sommarskog.se> - 2014-11-28 22:47 +0100
            Re: CASE issue Jim <jgeissman@socal.rr.com> - 2014-11-28 17:19 -0800
      Re: CASE issue "twenty-six@b-mint.net" <twenty-six@b-mint.net> - 2014-11-24 13:32 +0000
        Re: CASE issue Erland Sommarskog <esquel@sommarskog.se> - 2014-11-24 14:25 +0000
          Re: CASE issue "twenty-six@b-mint.net" <twenty-six@b-mint.net> - 2014-11-24 16:06 +0000
      Re: CASE issue Lennart Jonsson <erik.lennart.jonsson@gmail.com> - 2014-11-24 17:18 +0100
        Re: CASE issue Erland Sommarskog <esquel@sommarskog.se> - 2014-11-24 23:37 +0100
          Re: CASE issue Lennart Jonsson <erik.lennart.jonsson@gmail.com> - 2014-11-25 06:25 +0100
            Re: CASE issue Jim <jgeissman@socal.rr.com> - 2014-11-28 16:07 -0800
              Re: CASE issue Erland Sommarskog <esquel@sommarskog.se> - 2014-11-29 10:43 +0100

#1840 — CASE issue

From"twenty-six@b-mint.net" <twenty-six@b-mint.net>
Date2014-11-24 10:22 +0000
SubjectCASE issue
Message-ID<547306f8$0$41749$c3e8da3$5d8fb80f@news.astraweb.com>
Hello,   I'm trying to write a query to anonymise some data so need to 
generate a random birth month.

I'm generating random numbers okay, but am trying to decode the month 
with case statement:

select
case   cast(rand(checksum(newid()))*12 as int)+1
		when 1  then 'Jan'
		when 2  then 'Feb'
		when 3  then 'Mar'
		when 4  then 'Apr'
		when 5  then 'May'
		when 6  then 'Jun'
		when 7  then 'Jul'
		when 8  then 'Aug'
		when 9  then 'Sep'
		when 10 then 'Oct'
		when 11 then 'Nov'
		when 12 then 'Dec'
		when 13 then 'was 13!'
		when 0 then 'was 0!'
		else 'Unknown'
end
  from sysobjects


When I run this query I get lots of 'Unknown'  values, but I'm not sure 
why. If I just select distinct cast(rand(checksum(newid()))*12 as int)+1 
  I get the values 1-12 as expected.   It's not 0 or 13,  and if I put 
an ifnull to convert null to 13 then I still don't get any 'was 13!' 
entries.

So what am I missing?

Thanks,

Michael

[toc] | [next] | [standalone]


#1841

FromErland Sommarskog <esquel@sommarskog.se>
Date2014-11-24 11:26 +0000
Message-ID<XnsA3EF7E8B63B6CYazorman@127.0.0.1>
In reply to#1840
twenty-six@b-mint.net (twenty-six@b-mint.net) writes:
> When I run this query I get lots of 'Unknown'  values, but I'm not sure 
> why. 

This happens because

    CASE expr WHEN val1 THEN ....
              WHEN val2 THEN ....

is a shortcut for

   CASE WHEN expr = val1 THEN
        WHEN expr = val2 THEN

and thus the expression gets evaluated multiple times and then it goes 
downhill from there.

Set up a mapping table instead.


-- 
Erland Sommarskog, SQL Server MVP, esquel@sommarskog.se

Books Online for SQL Server 2005 at
http://www.microsoft.com/technet/prodtechnol/sql/2005/downloads/books.mspx
Books Online for SQL Server 2000 at
http://www.microsoft.com/sql/prodinfo/previousversions/books.mspx

[toc] | [prev] | [next] | [standalone]


#1842

Frombradbury9 <ray.bradbury9@gmail.com>
Date2014-11-24 04:16 -0800
Message-ID<3fc10276-8769-4885-ad67-1a5aee9dbb5c@googlegroups.com>
In reply to#1841
El lunes, 24 de noviembre de 2014 12:26:31 UTC+1, Erland Sommarskog  escribió:
> twenty-six writes:
> > When I run this query I get lots of 'Unknown'  values, but I'm not sure 
> > why. 
> 
> This happens because
> 
>     CASE expr WHEN val1 THEN ....
>               WHEN val2 THEN ....
> 
> is a shortcut for
> 
>    CASE WHEN expr = val1 THEN
>         WHEN expr = val2 THEN
> 
> and thus the expression gets evaluated multiple times and then it goes 
> downhill from there.
> 
> Set up a mapping table instead.
> 

In the MSDN doc it does not mention anything about being a shortcut, and I supposed it was not the case. Good to know that to avoid future errors.

> -- 
> Erland Sommarskog, SQL Server MVP
> 
> Books Online for SQL Server 2005 at
> http://www.microsoft.com/technet/prodtechnol/sql/2005/downloads/books.mspx
> Books Online for SQL Server 2000 at
> http://www.microsoft.com/sql/prodinfo/previousversions/books.mspx

[toc] | [prev] | [next] | [standalone]


#1845

FromErland Sommarskog <esquel@sommarskog.se>
Date2014-11-24 14:28 +0000
Message-ID<XnsA3EF9D686D618Yazorman@127.0.0.1>
In reply to#1842
bradbury9 (ray.bradbury9@gmail.com) writes:
> In the MSDN doc it does not mention anything about being a shortcut, and
> I supposed it was not the case. Good to know that to avoid future
> errors. 

Indeed. Books Online leaves no doubt that it works like twenty-six expected.
I need to discuss this with Microsoft. Will first have to check older 
versions.

-- 
Erland Sommarskog, SQL Server MVP, esquel@sommarskog.se

Books Online for SQL Server 2005 at
http://www.microsoft.com/technet/prodtechnol/sql/2005/downloads/books.mspx
Books Online for SQL Server 2000 at
http://www.microsoft.com/sql/prodinfo/previousversions/books.mspx

[toc] | [prev] | [next] | [standalone]


#1850

FromErland Sommarskog <esquel@sommarskog.se>
Date2014-11-28 22:47 +0100
Message-ID<XnsA3F3E7E5D4C04Yazorman@127.0.0.1>
In reply to#1845
Erland Sommarskog (esquel@sommarskog.se) writes:
> Indeed. Books Online leaves no doubt that it works like twenty-six
> expected. I need to discuss this with Microsoft. Will first have to
> check older versions. 

It seems like in SQL 6.5 it works like described in Books Online. SQL 2000
works like later versions as does SQL 7. Although, note that there are 
two patterns here: newid() and a subquery like in:

 select
   case  (SELECT a FROM bluddrig)
         when 1  then 'Jan'
         when 2  then 'Feb'
         when 3  then 'Mar'
         when 4  then 'Apr'
         when 5  then 'May'
         when 6  then 'Jun'
         when 7  then 'Jul'
         when 8  then 'Aug'
         when 9  then 'Sep'
         when 10 then 'Oct'
         when 11 then 'Nov'
         when 12 then 'Dec'
         when 13 then 'was 13!'
         when 0 then 'was 0!'
         else 'Unknown'
   end
     from sysobjects


newid() is overall special, since it's reevaluated for every row, while
other built-in functions are evaluated once - at least as they only appear
once.

There is no newid() on SQL 6.5, so I can say what happens there. But on SQL 
7 and later, the query with the subquery, has 14 access to the table 
bluddrig - SQL 6.5 has one.

I have not gotten any response, but the likelihood that Microsoft would
accept this as a regression from 6.5 and change it is minimal. Not the
least since there is a possible backwards compatibility here.

So I have filed a doc bug: 
https://connect.microsoft.com/SQLServer/feedback/details/1042044



-- 
Erland Sommarskog, Stockholm, esquel@sommarskog.se

[toc] | [prev] | [next] | [standalone]


#1852

FromJim <jgeissman@socal.rr.com>
Date2014-11-28 17:19 -0800
Message-ID<MPG.2ee2beff52f3f9b3989691@news.powerusenet.com>
In reply to#1850
In article <XnsA3F3E7E5D4C04Yazorman@127.0.0.1>, esquel@sommarskog.se 
says...
> 
> Erland Sommarskog (esquel@sommarskog.se) writes:
> > Indeed. Books Online leaves no doubt that it works like twenty-six
> > expected. I need to discuss this with Microsoft. Will first have to
> > check older versions. 
> 
> It seems like in SQL 6.5 it works like described in Books Online. SQL 2000
> works like later versions as does SQL 7. Although, note that there are 
> two patterns here: newid() and a subquery like in:
> 
>  select
>    case  (SELECT a FROM bluddrig)
>          when 1  then 'Jan'
>          when 2  then 'Feb'
>          when 3  then 'Mar'
>          when 4  then 'Apr'
>          when 5  then 'May'
>          when 6  then 'Jun'
>          when 7  then 'Jul'
>          when 8  then 'Aug'
>          when 9  then 'Sep'
>          when 10 then 'Oct'
>          when 11 then 'Nov'
>          when 12 then 'Dec'
>          when 13 then 'was 13!'
>          when 0 then 'was 0!'
>          else 'Unknown'
>    end
>      from sysobjects
> 
> 
> newid() is overall special, since it's reevaluated for every row, while
> other built-in functions are evaluated once - at least as they only appear
> once.
> 
> There is no newid() on SQL 6.5, so I can say what happens there. But on SQL 
> 7 and later, the query with the subquery, has 14 access to the table 
> bluddrig - SQL 6.5 has one.
> 
> I have not gotten any response, but the likelihood that Microsoft would
> accept this as a regression from 6.5 and change it is minimal. Not the
> least since there is a possible backwards compatibility here.
> 
> So I have filed a doc bug: 
> https://connect.microsoft.com/SQLServer/feedback/details/1042044

Very good.

[toc] | [prev] | [next] | [standalone]


#1843

From"twenty-six@b-mint.net" <twenty-six@b-mint.net>
Date2014-11-24 13:32 +0000
Message-ID<54733376$0$41649$c3e8da3$5d8fb80f@news.astraweb.com>
In reply to#1841
On 24/11/2014 11:26, Erland Sommarskog wrote:
> twenty-six@b-mint.net (twenty-six@b-mint.net) writes:
>> When I run this query I get lots of 'Unknown'  values, but I'm not sure
>> why.
>
> This happens because
>
>      CASE expr WHEN val1 THEN ....
>                WHEN val2 THEN ....
>
> is a shortcut for
>
>     CASE WHEN expr = val1 THEN
>          WHEN expr = val2 THEN
>
> and thus the expression gets evaluated multiple times and then it goes
> downhill from there.
>
> Set up a mapping table instead.
>
>
Ah I see, many thanks.    That would explain it nicely,  I really 
thought I'd found a bug.   :-)

By mapping table you mean create a table,  insert 12 rows  with  1, Jan 
   2, Feb  etc.  then join with that?

[toc] | [prev] | [next] | [standalone]


#1844

FromErland Sommarskog <esquel@sommarskog.se>
Date2014-11-24 14:25 +0000
Message-ID<XnsA3EF9CFA1AA2CYazorman@127.0.0.1>
In reply to#1843
twenty-six@b-mint.net (twenty-six@b-mint.net) writes:
> By mapping table you mean create a table,  insert 12 rows  with  1, Jan 
>    2, Feb  etc.  then join with that?
> 

Precisely.

-- 
Erland Sommarskog, SQL Server MVP, esquel@sommarskog.se

Books Online for SQL Server 2005 at
http://www.microsoft.com/technet/prodtechnol/sql/2005/downloads/books.mspx
Books Online for SQL Server 2000 at
http://www.microsoft.com/sql/prodinfo/previousversions/books.mspx

[toc] | [prev] | [next] | [standalone]


#1846

From"twenty-six@b-mint.net" <twenty-six@b-mint.net>
Date2014-11-24 16:06 +0000
Message-ID<54735789$0$41751$c3e8da3$5d8fb80f@news.astraweb.com>
In reply to#1844
On 24/11/2014 14:25, Erland Sommarskog wrote:
> twenty-six@b-mint.net (twenty-six@b-mint.net) writes:
>> By mapping table you mean create a table,  insert 12 rows  with  1, Jan
>>     2, Feb  etc.  then join with that?
>>
>
> Precisely.
>
Thanks.  Was just checking that I wasn't missing something "clever". 
The job's all done now.

Cheers,

Michael

[toc] | [prev] | [next] | [standalone]


#1847

FromLennart Jonsson <erik.lennart.jonsson@gmail.com>
Date2014-11-24 17:18 +0100
Message-ID<m4vlom$q0c$1@dont-email.me>
In reply to#1841
On 11/24/2014 12:26 PM, Erland Sommarskog wrote:
> twenty-six@b-mint.net (twenty-six@b-mint.net) writes:
>> When I run this query I get lots of 'Unknown'  values, but I'm not sure
>> why.
>
> This happens because
>
>      CASE expr WHEN val1 THEN ....
>                WHEN val2 THEN ....
>
> is a shortcut for
>
>     CASE WHEN expr = val1 THEN
>          WHEN expr = val2 THEN
>
> and thus the expression gets evaluated multiple times and then it goes
> downhill from there.
>

I think (don't have time to look it up now) the SQL-standard says that 
the result of the CASE statement is the first condition that evaluates 
to true. From your answer I get the impression that this is not true for 
SQL-server, correct?

Surely only one value is returned, but is it indeterministic which one?


/Lennart

[...]

[toc] | [prev] | [next] | [standalone]


#1848

FromErland Sommarskog <esquel@sommarskog.se>
Date2014-11-24 23:37 +0100
Message-ID<XnsA3EFF04705958Yazorman@127.0.0.1>
In reply to#1847
Lennart Jonsson (erik.lennart.jonsson@gmail.com) writes:
> I think (don't have time to look it up now) the SQL-standard says that 
> the result of the CASE statement is the first condition that evaluates 
> to true. From your answer I get the impression that this is not true for 
> SQL-server, correct?

That is indeed true. The issue is that the expression on the left-hand side 
is reevaluated for every branch in the CASE. 

newid() is a function that returns a randomly generated GUID, so it is a bit 
of a special case.
 



-- 
Erland Sommarskog, Stockholm, esquel@sommarskog.se

[toc] | [prev] | [next] | [standalone]


#1849

FromLennart Jonsson <erik.lennart.jonsson@gmail.com>
Date2014-11-25 06:25 +0100
Message-ID<m513rc$8vr$1@dont-email.me>
In reply to#1848
On 11/24/2014 11:37 PM, Erland Sommarskog wrote:
> Lennart Jonsson (erik.lennart.jonsson@gmail.com) writes:
>> I think (don't have time to look it up now) the SQL-standard says that
>> the result of the CASE statement is the first condition that evaluates
>> to true. From your answer I get the impression that this is not true for
>> SQL-server, correct?
>
> That is indeed true. The issue is that the expression on the left-hand side
> is reevaluated for every branch in the CASE.
>

I see, thanks


/Lennart

[toc] | [prev] | [next] | [standalone]


#1851

FromJim <jgeissman@socal.rr.com>
Date2014-11-28 16:07 -0800
Message-ID<MPG.2ee2ae00cb38741598968b@news.powerusenet.com>
In reply to#1849
In article <m513rc$8vr$1@dont-email.me>, erik.lennart.jonsson@gmail.com 
says...
> 
> On 11/24/2014 11:37 PM, Erland Sommarskog wrote:
> > Lennart Jonsson (erik.lennart.jonsson@gmail.com) writes:
> >> I think (don't have time to look it up now) the SQL-standard says that
> >> the result of the CASE statement is the first condition that evaluates
> >> to true. From your answer I get the impression that this is not true for
> >> SQL-server, correct?
> >
> > That is indeed true. The issue is that the expression on the left-hand side
> > is reevaluated for every branch in the CASE.
> >
> 
> I see, thanks
> 
> 
> /Lennart

I believe RAND() is evaluated once at the beginning, while NEWID() is 
evaluated each time. So one solution would be to evaluate the NEWID() 
version and park the result in a variable and use the variable, or use 
RAND() but base it on a seed that doesn't involve NEWID(), or at least 
if it does, determine it outside of the CASE statement.


[toc] | [prev] | [next] | [standalone]


#1853

FromErland Sommarskog <esquel@sommarskog.se>
Date2014-11-29 10:43 +0100
Message-ID<XnsA3F46D04B264CYazorman@127.0.0.1>
In reply to#1851
Jim (jgeissman@socal.rr.com) writes:
> I believe RAND() is evaluated once at the beginning, while NEWID() is 
> evaluated each time. So one solution would be to evaluate the NEWID() 
> version and park the result in a variable and use the variable, or use 
> RAND() but base it on a seed that doesn't involve NEWID(), or at least 
> if it does, determine it outside of the CASE statement.
> 

I don't think that would work well, because you want a new random number
per row. You could use a column on the row as seed - but then it would 
be deterministic. Look at this.

SELECT rand(), rand(object_id) FROM sys.objects


-- 
Erland Sommarskog, Stockholm, esquel@sommarskog.se

[toc] | [prev] | [standalone]


Back to top | Article view | comp.databases.ms-sqlserver


csiph-web