KDB type error - whilst using functional select/updates - function

I have the below two functions - the idea here is that id like to create percentiles of bpsAum for different programmes, i also have another function for bpsTrn, id like the limits table to be one single function that both can share. This however, returns a type error, I think it has to do with me using functional selects and updates within the functions. would appreciate any advice here. Outside of the function, running line by line this works fine, just not when packaged into function.
.tca.dailySlippageDistribution4:{[Dte;lookback;thresh]
tab:select bpsAum:(sum ArrivalSlippageUSD % first TradingLevel),sum TurnoverUSD by ProgrammeName,date from fullSlipTable where date within(Dte - 1500;Dte);
prog: exec distinct ProgrammeName from tab;
dtes: exec distinct date from tab;
Dte2:Dte - lookback;
Dte2:?[Dte2 in dtes;Dte2;?[(Dte2-1) in dtes;Dte2:Dte2-1;?[(Dte2-2) in dtes;Dte2:(Dte2-2);Dte2]]];
Dte:?[Dte in dtes;Dte;?[(Dte-1) in dtes;Dte:Dte-1;?[(Dte-2) in dtes;Dte:(Dte-2);Dte]]];
st:dtes?Dte;
ed:dtes?Dte2;
distwindow:(st-ed)-1;
metric:`bpsAum;
maW:0;
Limits:(uj/){[tab;thresh;distwindow;metric;maW;x] LimitsTable4[tab;thresh;distwindow;metric;maW;x]}[tab;thresh;distwindow;metric;maW;] each prog;
tab:ej[`date`ProgrammeName;tab;Limits];
tab};
LimitsTable4:{[tab;thresh;distwindow;metric;maW;prog]
tab: select from tab where ProgrammeName = prog;
tab:$[metric ~ `bpsTrn;![tab;();0b;(enlist `maRunRate)!(enlist (mavg;maW;metric))];tab];
dateList: exec date from tab;
LList:$[`maRunRate in cols tab;?[tab;();();`maRunRate];?[tab;();();`metric]];
ltk:`float$swin[.dashFn.getPercentile[thresh(1);];distwindow;LList];
utk:`float$swin[.dashFn.getPercentile[thresh(0);];distwindow;LList];
tab:?[metric ~ `bpsAum;([]date:dateList;ProgrammeName:prog;bpsAum:LList;upperLimit:utk;lowerLimit:ltk);([]date:dateList;ProgrammeName:prog;maBpsTrn:LList;upperLimit:utk;lowerLimit:ltk)];
tab:(-1*distwindow)# tab};

Related

How to get rid of "the expression you entered exceeds the1,024-character limit for the query design

How to get rid of "the expression you entered exceeds the 1,024-character limit for the query design? As I would need to extract the huge data based on the query in the access below.
Please see my query below. Any help is appreciated.
SELECT dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.Year, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.Month, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.Day, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.PERIOD, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.CONFIGURATIONNAME, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.CONNECTIONMEMBERNAME, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.VALUE, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.PRICINGRUNGROUPCODE, DateValue([dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING]![STARTDATE]) AS STARTDATE
FROM dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING, Input_BP
WHERE (((dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.PRICINGRUNGROUPCODE)="BP1B") AND ((DateValue([dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING]![STARTDATE])) Between #4/1/2021# And #4/30/2021#))
GROUP BY dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.Year, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.Month, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.Day, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.PERIOD, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.CONFIGURATIONNAME, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.CONNECTIONMEMBERNAME, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.VALUE, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.PRICINGRUNGROUPCODE, DateValue([dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING]![STARTDATE])
HAVING (((dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300140218" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300140226" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300140952" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300310001" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300313005" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300352052" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300469013" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300473072" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300482024" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300582096" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300582120" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300602001" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300629020" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300654028" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300670016" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300761021" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300774099" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300786051" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300786069" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300786085" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300843142" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300894517" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300897973" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300897981" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300964005" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300992725" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300992733" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300992741" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301001294" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301001302" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301001310" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301001328" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301003407" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301003464" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301003472" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301010147" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301010154" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301030434" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301030558" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301035045" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301035052" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301035060" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301035144" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301035151" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301035169" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301035276" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301035284" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301035300" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301035318" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301035326" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301035334" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301036027" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301040052" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301047008" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301049269" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301049293" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301049301" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301049319" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301049343" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301064003" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301128006" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301176898" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301218849" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9301344538"));
Thanks
Using an alias for the table name and replacing OR col = val1 OR col = val1 OR col2 = val ... with col in (val1, val2, val3, ...) will save you a lot of characters. It will also make the code a lot easier to understand. I also removed the reference to Input_BP, which did not seem to be contributing anything except the possibility of a ton of duplicate results.
SELECT T.Year,
T.Month,
T.Day,
T.PERIOD,
T.CONFIGURATIONNAME,
T.CONNECTIONMEMBERNAME,
T.VALUE,
T.MSSLID,
T.PRICINGRUNGROUPCODE,
DateValue([T]![STARTDATE]) AS STARTDATE
FROM dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING As T
WHERE (((T.PRICINGRUNGROUPCODE)="BP1B")
AND ((DateValue([T]![STARTDATE])) Between #4/1/2021# And #4/30/2021#))
GROUP BY T.Year,
T.Month,
T.Day,
T.PERIOD,
T.CONFIGURATIONNAME,
T.CONNECTIONMEMBERNAME,
T.VALUE,
T.MSSLID,
T.PRICINGRUNGROUPCODE,
DateValue([T]![STARTDATE])
HAVING (T.MSSLID IN ("9300140218", ...));
If you want to be able to access the query design builder, I recommend copying and pasting maybe half of the repeated fields towards the bottom to a note/word file so you can delete some of the fields in SQL? And I'm not sure if this is for a report or a form, but try to use VBA to reduce the query; or maybe use the function Right() for the field MSSLID so you don't have to write the first "9300"?
(This is just a reduced version of your code; I'm not sure if you're making a report or form or if you just wanted to make a query)
SELECT dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.Year, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.Month, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.Day, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.PERIOD, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.CONFIGURATIONNAME, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.CONNECTIONMEMBERNAME, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.VALUE, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.PRICINGRUNGROUPCODE, DateValue([dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING]![STARTDATE]) AS STARTDATE FROM dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING, Input_BP WHERE (((dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.PRICINGRUNGROUPCODE)="BP1B") AND ((DateValue([dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING]![STARTDATE])) Between #4/1/2021# And #4/30/2021#)) GROUP BY dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.Year, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.Month, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.Day, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.PERIOD, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.CONFIGURATIONNAME, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.CONNECTIONMEMBERNAME, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.VALUE, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID, dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.PRICINGRUNGROUPCODE, DateValue([dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING]![STARTDATE]) HAVING (((dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300140218" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300140226" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300140952" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300310001" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300313005" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300352052" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300469013" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300473072" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300482024" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300582096" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300582120" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300602001" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300629020" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300654028" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300670016" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300761021" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300774099" Or (dbo_plp_MCSEMVALCONSUMPTIONVALIDATIONVIEW_BILLING.MSSLID)="9300786051"));
Let me know if this helps!

Dynamic Naming of Matlab Function

I currently have a MATLAB function that looks like this:
function outfile=multi_read(modelfrom,modelto,type)
models=[modelfrom:1:modelto];
num_models=length(models);
model_path='../MODELS/GRADIENT/'
for id=1:num_models
fn=[model_path num2str(models(id)) '/']; %Location of file to be read
outfile=model_read(fn,type); %model_read is a separate function
end
end
The idea of this function is to execute another function model_read for a series of files, and output these files to the workspace (not to disk). Note that the output from model_read is a structure! I want the function to save the file to the workspace using sequential names, similar to typing:
file1=multi_read(1,1,x)
file2=multi_read(2,2,x)
file3=multi_read(3,3,x)
etc.
which would give file1, file2 and file3 in the workspace, but instead by recalling the command only once, something like:
multi_read(1,3,x)
which would give the same workspace output.
Essentially my questions is, how do I get a function to output variables with multiple names without having to recall the function multiple times.
As suggested in the comment I would try this approach which is more robust, at least IMHO:
N = tot_num_of_your_files; %whatever it is
file = cellfun(#(i)multi_read(i,i,x),mat2cell(1:N,1,ones(1,N)),...
'UniformOutput' , false); %(x needs to be defined)
You will recover objects by doing file{i}.
Here is code to do what you ask:
for i = 1:3
istr=num2str(i)
line = ['file' istr '= multi_read(' istr ', ' istr ', x)']
eval(line)
end
Alternatively, here is code to do what you should want:
for i = 1:3
file{i} = multi_read(i,i,x)
end

Passing variables into a function in Lua

I'm new to Lua, so (naturally) I got stuck at the first thing I tried to program. I'm working with an example script provided with the Corona Developer package. Here's a simplified version of the function (irrelevant material removed) I'm trying to call:
function new( imageSet, slideBackground, top, bottom )
function g:jumpToImage(num)
print(num)
local i = 0
print("jumpToImage")
print("#images", #images)
for i = 1, #images do
if i < num then
images[i].x = -screenW*.5;
elseif i > num then
images[i].x = screenW*1.5 + pad
else
images[i].x = screenW*.5 - pad
end
end
imgNum = num
initImage(imgNum)
end
end
If I try to call that function like this:
local test = slideView.new( myImages )
test.jumpToImage(2)
I get this error:
attempt to compare number with nil
at line 225. It would seem that "num" is not getting passed into the function. Why is this?
Where are you declaring g? You're adding a method to g, which doesn't exist (as a local). Then you're never returning g either. But most likely those were just copying errors or something. The real error is probably the notation that you're using to call test:jumpToImage.
You declare g:jumpToImage(num). That colon there means that the first argument should be treated as self. So really, your function is g.jumpToImage(self, num)
Later, you call it as test.jumpToImage(2). That makes the actual arguments of self be 2 and num be nil. What you want to do is test:jumpToImage(2). The colon there makes the expression expand to test.jumpToImage(test, 2)
Take a look at this page for an explanation of Lua's : syntax.

R function scope

I am trying to create a function for a series of rounding work in R, I have percentage, decimals, etc, each of them need to be rounded differently.
I start writing the function by first picking up the object I want, but I fail to do that already, here's the code:
roundings <- function(obj.head)
{obj.list <- ls(pattern=obj.head)
obj.list
}
Suppose I have two object A1 and B1, I suppose if I run roundings("A"), A1 should appear as the function output, but it didn't.
What have I done wrong? Thanks.
The call to ls is searching the current environment within the function and does not find any objects to match. You can specify the envir parameter in ls with .GlobalEnv. Thus your code becomes:
roundings <- function(obj.head)
{
obj.list <- ls(pattern = obj.head, envir = .GlobalEnv)
obj.list
}
I found the reason, I should have added envir=.GlobalEnv inside the ls parameters.

MySQL - Perl: How to get array of zip codes within submitted "x" miles of submitted "zipcode" in Perl example

I have found many calculations here and some php examples and most are just over my head.
I found this example:
SELECT b.zip_code, b.state,
(3956 * (2 * ASIN(SQRT(
POWER(SIN(((a.lat-b.lat)*0.017453293)/2),2) +
COS(a.lat*0.017453293) *
COS(b.lat*0.017453293) *
POWER(SIN(((a.lng-b.lng)*0.017453293)/2),2))))) AS distance
FROM zips a, zips b
WHERE
a.zip_code = '90210' ## I would use the users submitted value
GROUP BY distance
having distance <= 5; ## I would use the users submitted value
But, I am having trouble understanding how to implement the query with my database.
It looks like that query has all I need.
However, I cannot even find/understand what b.zip_code actually is! (whats the b. and zips a, zips b?)
I also do not need the state in the query.
My mySQL db structure is like this:
ZIP | LAT | LONG
33416 | 26.6654 | -80.0929
I wrote this in attempt to return some kind of results (not based on above query) but, it only kicks out one zip code.
## Just for a test BUT, in reality I desire to SELECT a zip code WHERE ZIP = the users submitted zip code
## not by a submitted lat lon. I left off the $connect var, assume it's there.
my $set1 = (26.6654 - 0.20);
my $set2 = (26.6654 + 0.20);
my $set3 = (-80.0929 - 0.143);
my $set4 = (-80.0929 + 0.143);
my $test123 = $connect->prepare(qq{SELECT `ZIP` FROM `POSTAL`
WHERE `LAT` >= ? AND `LAT` <= ?
AND `LONG` >= ? AND `LONG` <= ?}) or die "$DBI::errstr";
$test123->execute("$set1","$set2","$set3","$set4") or die "$DBI::errstr";
my $cntr;
while(#zip = $test123->fetchrow_array()) {
print qq~$zip[$cntr]~;
push(#zips,$zip[$cntr]);
$cntr++;
}
As you can see, I am quite the novice so, I need some hand holding here with verbose explanation.
So, in Perl, how can I push zip codes into an array from a USER SUBMITTED ZIP CODE and user submitted DISTANCE in miles. Can be a square instead of a circle, not really that critical of a feature. Faster is better.
I'll tackle the small but crucial part of the question:
However, I cannot even find/understand what b.zip_code actually is! (whats the "b." and "zips a, zips b"?)
Basically, the query joins two tables. BUT, both tables being joined are in fact the same table - "zips" (in other words, it joins "zips" table to itself"). Of course, since the rest of the query needs to understand when you are referring to the first copy of the "zips" table and when to the second copy of the "zips" table, you are giving a table alias to each copy - to wit, "a" and "b"'.
So, "b.xxx" means "column xxx from table zips, from the SECOND instance of that table being joined".
I don't see what's wrong with your first query. You have latitude and longitude in your database (if I'm understanding, you're comparing a single entry to all others). You don't need to submit or return the state that's just part of the example. Make the first query work like this:
my $query = "SELECT b.zip_code,
(3956 * (2 * ASIN(SQRT(
POWER(SIN(((a.lat-b.lat)*0.017453293)/2),2) +
COS(a.lat*0.017453293) *
COS(b.lat*0.017453293) *
POWER(SIN(((a.lng-b.lng)*0.017453293)/2),2))))) AS distance
FROM zips a, zips b WHERE
a.zip_code = ?
GROUP BY distance having distance <= ?";
my $sth = $dbh->prepare($query);
$sth->execute( $user_submitted_zip, $user_submitted_distance );
while( my ($zip, $distance) = $sth->fetchrow() ) ) {
# do something
}
This won't be that fast, but if you have a small record set ( less than 30k rows ) it should be fine. If you really want to go faster you should look into a search engine such as Sphinx which will do this for you.
fetchrow_array returns a list of list references, essentially a two-dimensional array, where each row represents a different result from the database query and each column represents a field from the query (in your case, there is only one field, or column, per row).
Calling while ($test123->fetchrow_array()) will cause an infinite loop as your program executes the query over and over again. If the query returns results, then the while condition will be satisfied and the loop will repeat. The usual idiom would be to say something more like for my $row ($test123->fetchrow_array()) { ..., which will only execute the query once and then iterate over the results.
Each result is a list reference, and the zip code you are interested in is in the first (and only) column, so you could accumulate the results in an array like this:
my #zips = (); # for final results
for my $row ($test123->fetchrow_array()) {
push #zips, $row->[0];
}
or even more concisely with Perl's map statement:
my #zips = map { $_->[0] } $test123->fetchrow_array()
which does the same thing.