Anyone know why I am getting a rank error here?
test:([]side:())
test insert s
test insert bselect side:$[side=
b;1;side=s;2;0] from test
rank`
the if/else works fine on its own just inside the select it throws an error
Anyone know why I am getting a rank error here?
test:([]side:())
test insert s
test insert bselect side:$[side=
b;1;side=s;2;0] from test
rank`
the if/else works fine on its own just inside the select it throws an error
You need to use the vector conditional ? instead of the atom conditional $<o:p></o:p>
<o:p> </o:p>
q)select side:?[side=b;1;?[side=
s;2;0]] from test<o:p></o:p>
<o:p> </o:p>
but it would be better to do a search instead, like:<o:p></o:p>
<o:p> </o:p>
q)\ts:10000 select side:?[side=b;1;?[side=
s;2;0]] from test<o:p></o:p>
100 1728<o:p></o:p>
q)\ts:10000 select ``b`s?side from test<o:p></o:p>
30 816<o:p></o:p>
<o:p> </o:p>
And significantly better for larger sets:<o:p></o:p>
q)test2:10000000?test<o:p></o:p>
q)\ts select side:?[side=b;1;?[side=
s;2;0]] from test2<o:p></o:p>
198 419431120<o:p></o:p>
q)\ts select ``b`s?side from test2<o:p></o:p>
14 134218400<o:p></o:p>
<o:p> </o:p>
<o:p> </o:p>
From: personal-kdbplus@googlegroups.com [mailto:personal-kdbplus@googlegroups.com] On Behalf Of Roni Hoffman
Sent: Thursday, May 21, 2015 1:55 PM
To: personal-kdbplus@googlegroups.com
Subject: [personal kdb+] Rank error using if/else<o:p></o:p>
<o:p> </o:p>
Anyone know why I am getting a rank error here? <o:p></o:p>
<o:p> </o:p>
test:(side:())
test insert
s
test insert
b
select side:$[side=b;1;side=
s;2;0] from test
`rank<o:p></o:p>
<o:p> </o:p>
the if/else works fine on its own just inside the select it throws an error<o:p></o:p>
–
Submitted via Google Groups
Hi Roni,
Reason why you are getting rank is because it is the incorrect logic/rank for the if/else statement. If you use 0N! in your statement
you can see “01b” outputted first. 0N! can be useful here for debugging.
select side:$[0N!side=b;1;side=
s;2;0] from test
As David pointed out you should use the vector conditional, or you could even use $[;;]each x
e.g.
select side:{$[x=b;1;x=
s;2;0]}each side from test
but I wouldn’t recommend it as the vector would be much faster here.
However there is a better method for this and this also helps you out much more if you are going to have more conditions (and they follow the same search and replace requirement). This is done by creating a dictionary/map and using simple indexing. Writing out cumulative conditions out can become tiresome, and slow.
q)\ts select side:?[side=b;1;?[side=
s;2;0]] from test2
321 419431312
q)\ts select side:0^(b
s!1 2) side from test2
79 268436224
//the 0 fills itself takes 20% of the time!!
q)\ts select side:(b
s!1 2) side from test2
62 268436112
//confirm results match
q)(select side:0^(b
s!1 2) side from test2)~select side:?[side=b;1;?[side=
s;2;0]] from test2
1b
this mapping/indexing really becomes useful when you have more than say 2 conditions. It gives you the flexibility to replace with what you want at very good speed in short code.
//lets make 24 letters of the alphabet be replaced with 1-24, and the rest with 0
//im not going to write out all the conditionals so make ourselves a helper function
f:{?[z;();0b;(enlist y)!enlist {(?;(=;z;enlist first y);last y;x)}[;;y] over reverse x]}
//lets make ourselves a table with more ids
q)test3:(side:10000000?`1)
q)\ts f[(2_($'.Q.a),'1+til 26),0;
side;test3]
1487 301997456
q)\ts select 0^(2_((`$'.Q.a)!1+til 26)) side from test3
161 318768128
//confirm results match
q)(select 0^(2_(($'.Q.a)!1+til 26)) side from test3)~f[(2_(
$'.Q.a),'1+til 26),0;`side;test3]
1b
Hope this is useful,
Sean
Thanks Sean
Thanks David, that helps