TSQL Index odd and even sequence steps - sql

I have a gritty industrial control problem i'm trying to solve with T-SQL.
The goal is to calculate an index position for each of two pallet loading robots, positioned in one of two ranges; 2 to 78 (robot 1) and 4 to 80 (robot 2).
Each robot indexes in steps of 4 so complete coverage of 80 spots on the pallet is achieved. The robots work side by side with a minimum spacing of 2 spots while they move along the pallet.
Two sized boxes can be placed on the pallet, one twice as long as the other. If two small boxes are placed side by side taking up 1 spot each, a single larger box can be placed on top, taking up 2 spots until a maximum height is reached. Thus the spot number for a small box is always odd and for a large box is always even and the robot index number is always even. e.g. (see diagram) from index position 14 spots 13 and 15 are loaded, and from index 20 spots 19 and 21 can be loaded.
Robot Index Positions
I need a conversion formula that calculates the Index number for a given Spot and Robot.
The calculated Index column should look like the following:
Spot Robot Index
1 1 2
2 1 2
3 1 2
- - -
13 1 14
14 1 14
15 1 14
16 2 16
17 2 16
18 1 18
19 2 20
- - -
- - -
77 1 78
78 1 78
79 2 80
80 2 80
One way would be to do an update to the Index column with every possible combination of Spot and Robot using a simple CASE WHEN selection or maybe do lookups on a reference table holding every possible combination. What I would like to explore (if any math wizards are inclined!) is a math formula that calculate the Index value.
So far I've come up with the following by converting formula developed for use in Excel. The Robot 2 section is incomplete. The 95 to 99 values are for error checking.
UPDATE MovesTable SET [Index] =
CASE
WHEN Robot = 1 THEN
CASE
WHEN Spot%4 = 0 THEN '99'
WHEN Spot = 1 or Spot = 2 or Spot = 3 THEN '02'
WHEN Spot = 5 or Spot = 6 or Spot = 7 THEN '06'
WHEN Spot = 9 or Spot = 10 or Spot = 11 THEN '10'
WHEN Spot%10 = 4 THEN CONCAT(Spot/10,'4')
WHEN Spot < 57 AND (((Spot/10)%2 = 1 AND (Spot%10)%2 = 1) AND (Spot%10 = 3 OR Spot%10 = 5)) THEN CONCAT(Spot/10,'4')
WHEN Spot%10 = 8 THEN CONCAT(Spot/10,'8')
WHEN Spot < 57 AND (((Spot/10)%2 = 1 AND (Spot%10)%2 = 1) AND (Spot%10 = 7 OR Spot%10 = 9)) THEN CONCAT(Spot/10,'8')
WHEN Spot%10 = 2 THEN CONCAT(Spot/10,'2')
WHEN Spot < 57 AND (((Spot/10)%2 = 1 AND (Spot%10)%2 = 0) AND (Spot%10 = 1 OR Spot%10 = 3)) THEN CONCAT(Spot/10,'2')
WHEN Spot%10 = 6 THEN CONCAT(Spot/10,'6')
WHEN Spot < 57 AND (((Spot/10)%2 = 0 AND (Spot%10)%2 = 1) AND (Spot%10 = 5 OR Spot%10 = 7)) THEN CONCAT(Spot/10,'6')
WHEN Spot%10 = 0 THEN CONCAT(Spot/10,'')
WHEN Spot = 49 THEN '50'
WHEN Spot < 57 AND (((Spot/10)%2 = 0 AND (Spot%10)%2 = 1) AND Spot%10 = 9) THEN '30'
WHEN Spot < 57 AND (((Spot/10)%2 = 1 AND (Spot%10)%2 = 1) AND Spot%10 = 1) THEN CONCAT(Spot/10,'0')
WHEN Spot > 56 AND (((Spot/10)%2 = 1 AND (Spot%10)%2 = 1) AND (Spot%10 = 7 OR Spot%10 = 9)) THEN CONCAT(Spot/10,'8')
WHEN Spot > 56 AND (((Spot/10)%2 = 0 AND (Spot%10)%2 = 1) AND (Spot%10 = 1 OR Spot%10 = 3)) THEN CONCAT(Spot/10,'2')
WHEN Spot > 56 AND (((Spot/10)%2 = 0 AND (Spot%10)%2 = 1) AND (Spot%10 = 5 OR Spot%10 = 7)) THEN CONCAT(Spot/10,'6')
ELSE '98'
END
ELSE
CASE
WHEN Robot = 2 THEN
CASE
WHEN (Spot%2 = 0 AND Spot%4 <> 0) OR (Spot = 1 OR Spot = 2) THEN '97'
WHEN Spot = 4 then '04'
WHEN Spot = 8 then '08'
WHEN Spot%4 = 0 THEN Spot
WHEN Spot = 2 OR Spot = 5 THEN '05'
WHEN Spot = 7 OR Spot = 9 THEN '08'
WHEN Spot = 19 THEN '20'
WHEN Spot = 39 THEN '40'
WHEN Spot = 59 THEN '60'
ELSE '96'
END
ELSE '95'
END
END

I tried to solve this mathematically, rather than by analyzing cases, etc. It matches all of your sample results:
declare #t table (Spot int, Robot int, [Index] int)
insert into #t(Spot,Robot,[Index]) values
(1 ,1 , 2 ),
(2 ,1 , 2 ),
(3 ,1 , 2 ),
(13 ,1 ,14 ),
(14 ,1 ,14 ),
(15 ,1 ,14 ),
(16 ,2 ,16 ),
(17 ,2 ,16 ),
(18 ,1 ,18 ),
(19 ,2 ,20 ),
(77 ,1 ,78 ),
(78 ,1 ,78 ),
(79 ,2 ,80 ),
(80 ,2 ,80 )
select *,
CONVERT(int,
ROUND((Spot +
CASE WHEN Robot = 1 THEN 2 ELSE 0 END
)/4.0,0)* 4 -
CASE WHEN Robot = 1 THEN 2 ELSE 0 END
) as Index2
from #t
The logic is "round to the nearest multiple of four" but we use a couple of expressions to offset Robot 1's results by 2.
Results:
Spot Robot Index Index2
----------- ----------- ----------- -----------
1 1 2 2
2 1 2 2
3 1 2 2
13 1 14 14
14 1 14 14
15 1 14 14
16 2 16 16
17 2 16 16
18 1 18 18
19 2 20 20
77 1 78 78
78 1 78 78
79 2 80 80
80 2 80 80

Related

Generating random values using numpy

I assign normal rv with mean 12 to ultimately generate order_date for my mock data. But when i am checking it out to see whether 12 is most used value, it turns out to be not. Any recommendations why it is the case...
def random_date_generator(month):
day_range = calendar.monthrange(2020, month)[1]
day = random.randint(1, day_range)
**first_hour = int(np.random.normal(12, 2))**
# second_hour = int(np.random.normal(18, 2))
hour = random.choices([first_hour])[0]
minute = random.randint(1, 59)
date = dt.datetime(2020, month, day, hour, minute).strftime("%Y/%m/%d %H:%M")
return date
columns = ['Order ID', 'Product', 'Quantity Ordered', 'Price Each', 'Order Date',
'Purchase Address', "Month"]
df = pd.DataFrame(columns=columns)
order_id = 123
for month_int in range(1, 13):
if month_int == 12:
order_amount = int(np.random.normal(100, 30))
if month_int == 11:
order_amount = int(np.random.normal(90, 30))
if month_int < 11:
order_amount = int(np.random.normal(60, 10))
for i in range(order_amount):
products_list = [product for product in products]
weights = [products[key][1] for key in products_list]
product = random.choices(products_list, weights=weights)[0]
price = products[product]
date = random_date_generator(month_int)
address = generate_random_addresses()
month = calendar.month_name[month_int]
df.loc[i] = [order_id, product, "NA" ,price, date, address, month_int]
order_id += 1
df.to_csv(f"{month}_data2.csv")
print(f"{month}_data2.csv")
break
january = pd.read_csv("January_data2.csv")
january["Hour"] = january["Order Date"].str[-5:-3]
january.groupby("Hour").count()
That is the output and as you see the most generated time is 12 but 10.
Unnamed: 0 Order ID Product Quantity Ordered Price Each Order Date Purchase Address Month
Hour
07 2 2 2 0 2 2 2 2
08 2 2 2 0 2 2 2 2
09 9 9 9 0 9 9 9 9
10 15 15 15 0 15 15 15 15
11 11 11 11 0 11 11 11 11
12 10 10 10 0 10 10 10 10
13 9 9 9 0 9 9 9 9
14 7 7 7 0 7 7 7 7
15 3 3 3 0 3 3 3 3

Two Condition Where-clause SQL

I need to filter some rows when 2 conditions are met, but not excluding the other rows.
Table:
idRow idMaster idList
1 10 45
2 10 46
3 10 47
4 11 10
5 11 98
6 14 56
7 16 28
8 20 55
Example:
When:
idMaster=10 and id List=45 (only show this combination for idMaster 10)
idMaster=11 and idList=98 (only show this combination for idMaster 11)
list all other rows as well.
Expected result:
idRow idMaster idList
1 10 45
5 11 98
6 14 56
7 16 28
8 20 55
Running SQL Server 2014
I tried combinations of CASE IF but all cases only filter the idMaster=10,11 and idList=45,98, excluding the other rows
Although you didn't mentioned the database name, this following query logic will be applicable for all databases-
SELECT *
FROM your_table
WHERE idMaster NOT IN (10,11)
OR (idMaster = 10 AND idList = 45)
OR (idMaster = 11 AND idList = 98)
You can indeed do this with a (nested) case. Hopefully this helps you understand better.
case idMaster
when 10 then case idList when 45 then 1 end
when 11 then case idList when 98 then 1 end
else 1
end = 1
This might be the best though:
not (idList = 10 and idList <> 45 or idList = 11 and idList <> 98)
Overall it's usually beneficial to avoid repeating that list of values in multiple places. Both of these avoid the need to keep things in sync when changes come.

Code if then statement by only using $ utility

How can I code this 'if' conditions in GAMS?
Set j/1*10/
S/1*6/;
Parameter
b(s,j) export this from excel
U(s,j) export from excel
M(s)/1 100,2 250,3 140,4 120,5 132/ export from excel
;
table b(s,j)
1 2 3 4 5 6 7 8 9 10
1 3 40 23 12 9 52 9 14 89 33
2 0 0 42 0 11 32 11 15 3 7
3 10 20 12 9 5 30 14 5 14 5
4 0 0 0 9 0 3 8 0 13 5
5 0 10 11 32 11 0 3 1 12 1
6 12 20 2 9 15 3 14 5 14 5
;
u(s,j)=0;
u(s,j)$(b(s,j))=1;
Variable delta(j); "binary"
After solving a model I got the value of delta ( suppose delta(1)=1, delta(5)=1). Then Set A is
A(j)$(delta.l(j)=1)=Yes; (A={1,5})
I want to calculate parameter R(s) according to the following :
If there is no j in A(j) s.t. j in u(s,j) then R(s)=M(s)
Else if there is a j in A(j) s.t. j in u(s,j) then R(s)=min{b(s,j): j in A(j) , j in u(s,j) }
Then R(1)=3, R(2)=11,R(3)=5, R(4)=120, R(5)=11,R(6)=12.
Is it possible to code this ' if then ' statement only by $ utility?
Thanks
Following on from the comments, I think this should work for you.
(Create a parameter that mimics your variable delta just for demonstration:)
parameter delta(j);
delta('1') = 1;
delta('5') = 1;
With loop and if/else:
Create parameter R(s). Then, looping over s , pick the minimum of b(s,A) across set A where b(s,A) is defined if the sum of b(s,A) is not zero (i.e. if one of the set is non-zero. Else, set R(s) equal to M(s).
Note, the loop is one solution to the issue you were having with mixed dimensions. And the $(b(s,A)) needs to be on the first argument of smin(.), not on the second argument.
parameter R(s);
loop(s,
if (sum(A, b(s,A)) ne 0,
R(s) = smin(A$b(s,A), b(s,A));
else
R(s) = M(s);
);
);
With $ command only (#Lutz in comments):
R(s)$(sum(A, b(s,A)) <> 0) = smin(A$b(s,A), b(s,A));
R(s)$(sum(A, b(s,A)) = 0) = M(s);
Gives:
---- 56 PARAMETER R
1 3.000, 2 11.000, 3 5.000, 4 120.000, 5 11.000, 6 12.000

Calculating Run Cost for lengths of Pipe & Pile

I work for a small company and we're trying to get away from Excel workbooks for Inventory control. I thought I had it figured out with help from (Nasser) but its beyond me. This is what I can get into a table, from there I need too get it to look like the table below.
My data
ID|GrpID|InOut| LoadFt | LoadCostft| LoadCost | RunFt | RunCost| AvgRunCostFt
1 1 1 4549.00 0.99 4503.51 4549.00 0 0
2 1 1 1523.22 1.29 1964.9538 6072.22 0 0
3 1 2 -2491.73 0 0 3580.49 0 0
4 1 2 -96.00 0 0 3484.49 0 0
5 1 1 8471.68 1.41 11945.0688 11956.17 0 0
6 1 2 -369.00 0 0 11468.0568 0 0
7 2 1 1030.89 5.07 5223.56 1030.89 0 0
8 2 1 314.17 5.75 1806.4775 1345.06 0 0
9 2 1 239.56 6.3 1508.24 1509.228 0 0
10 2 2 -554.46 0 0 954.768 0 0
11 2 1 826.24 5.884 4861.5961 1781.008 0 0
Expected output
ID|GrpID|InOut| LoadFt | LoadCostft| LoadCost | RunFt | RunCost| AvgRunCostFt
1 1 1 4549.00 0.99 4503.51 4549.00 4503.51 0.99
2 1 1 1523.22 1.29 1964.9538 6072.22 6468.4638 1.0653
3 1 2 -2491.73 1.0653 -2490.6647 3580.49 3977.7991 1.111
4 1 2 -96.00 1.111 -106.656 3484.49 3871.1431 1.111
5 1 1 8471.68 1.41 11945.0688 11956.17 15816.2119 1.3228
6 1 2 -369.00 1.3228 -488.1132 11468.0568 15328.0987 1.3366
7 2 1 1030.89 5.07 5223.56 1030.89 5223.56 5.067
8 2 1 314.17 5.75 1806.4775 1345.06 7030.0375 5.2266
9 2 1 239.56 6.3 1508.24 1509.228 8539.2655 5.658
10 2 2 -554.46 5.658 -3137.1346 954.768 5402.1309 5.658
11 2 1 826.24 5.884 4861.5961 1781.008 10263.727 5.7629
The first record of a group would be considered the opening balance. Inventory going into the yard have the ID of 1 and out of the yard are 2's. Load footage going into the yard always has a load cost per foot and I can calculate the the running total of footage. The first record of a group is easy to calculate the run cost and run cost per foot. The next record becomes a little more difficult to calculate. I need to move the average of run cost per foot forward to the load cost per foot when something is going out of the yard and then calculate the run cost and average run cost per foot again. Hopefully this makes sense to somebody and we can automate some of these calculations. Thanks for any help.
Here's an Oracle example I found;
SQL> select order_id
2 , volume
3 , price
4 , total_vol
5 , total_costs
6 , unit_costs
7 from ( select order_id
8 , volume
9 , price
10 , volume total_vol
11 , 0.0 total_costs
12 , 0.0 unit_costs
13 , row_number() over (order by order_id) rn
14 from costs
15 order by order_id
16 )
17 model
18 dimension by (order_id)
19 measures (volume, price, total_vol, total_costs, unit_costs)
20 rules iterate (4)
21 ( total_vol[any] = volume[cv()] + nvl(total_vol[cv()-1],0.0)
22 , total_costs[any]
23 = case SIGN(volume[cv()])
24 when -1 then total_vol[cv()] * nvl(unit_costs[cv()-1],0.0)
25 else volume[cv()] * price[cv()] + nvl(total_costs[cv()-1],0.0)
26 end
27 , unit_costs[any] = total_costs[cv()] / total_vol[cv()]
28 )
29 order by order_id
30 /
ORDER_ID VOLUME PRICE TOTAL_VOL TOTAL_COSTS UNIT_COSTS
---------- ---------- ---------- ---------- ----------- ----------
1 1000 100 1000 100000 100
2 -500 110 500 50000 100
3 1500 80 2000 170000 85
4 -100 150 1900 161500 85
5 -600 110 1300 110500 85
6 700 105 2000 184000 92
6 rows selected.
Let me say first off three things:
This is certainly not the best way to do it. There is a rule saying that if you need a while-loop, then you are most probably doing something wrong.
I suspect there is some calculation errors in your original "Expected output", please check the calculations since my calculated values are different according to your formulas.
This question could also be seen as a gimme teh codez type of question, but since you asked a decently formed question with some follow-up research, my answer is below. (So no upvoting since this is help for a specific case)
Now onto the solution:
I attempted to use my initial hint of the LAG statement in a nicely formed single update statement, but since you can only use a windowed function (aka LAG) inside a select or order by clause, that will not work.
What the code below does in short:
It calculates the various calculated fields for each record when they can be calculated and with the appropriate functions, updates the table and then moves onto the next record.
Please see comments in the code for additional information.
TempTable is a demo table (visible in the linked SQLFiddle).
Please read this answer for information about decimal(19, 4)
-- Our state and running variables
DECLARE #curId INT = 0,
#curGrpId INT,
#prevId INT = 0,
#prevGrpId INT = 0,
#LoadCostFt DECIMAL(19, 4),
#RunFt DECIMAL(19, 4),
#RunCost DECIMAL(19, 4)
WHILE EXISTS (SELECT 1
FROM TempTable
WHERE DoneFlag = 0) -- DoneFlag is a bit column I added to the table for calculation purposes, could also be called "IsCalced"
BEGIN
SELECT top 1 -- top 1 here to get the next row based on the ID column
#prevId = #curId,
#curId = tmp.ID,
#curGrpId = Grpid
FROM TempTable tmp
WHERE tmp.DoneFlag = 0
ORDER BY tmp.GrpID, tmp.ID -- order by to ensure that we get everything from one GrpID first
-- Calculate the LoadCostFt.
-- It is either predetermined (if InOut = 1) or derived from the previous record's AvgRunCostFt (if InOut = 2)
SELECT #LoadCostFt = CASE
WHEN tmp.INOUT = 2
THEN (lag(tmp.AvgRunCostFt, 1, 0.0) OVER (partition BY GrpId ORDER BY ID))
ELSE tmp.LoadCostFt
END
FROM TempTable tmp
WHERE tmp.ID IN (#curId, #prevId)
AND tmp.GrpID = #curGrpId
-- Calculate the LoadCost
UPDATE TempTable
SET LoadCost = LoadFt * #LoadCostFt
WHERE Id = #curId
-- Calculate the current RunFt and RunCost based on the current LoadFt and LoadCost plus the previous row's RunFt and RunCost
SELECT #RunFt = (LoadFt + (lag(RunFt, 1, 0) OVER (partition BY GrpId ORDER BY ID))),
#RunCost = (LoadCost + (lag(RunCost, 1, 0) OVER (partition BY GrpId ORDER BY ID)))
FROM TempTable tmp
WHERE tmp.ID IN (#curId, #prevId)
AND tmp.GrpID = #curGrpId
-- Set all our values, including the AvgRunCostFt calc
UPDATE TempTable
SET RunFt = #RunFt,
RunCost = #RunCost,
LoadCostFt = #LoadCostFt,
AvgRunCostFt = #RunCost / #RunFt,
doneflag = 1
WHERE ID = #curId
END
SELECT ID, GrpID, InOut, LoadFt, RunFt, LoadCost,
RunCost, LoadCostFt, AvgRunCostFt
FROM TempTable
ORDER BY GrpID, Id
The output with your sample data and a SQLFiddle demonstrating how it all works:
ID GrpID InOut LoadFt RunFt LoadCost RunCost LoadCostFt AvgRunCostFt
1 1 1 4549 4549 4503.51 4503.51 0.99 0.99
2 1 1 1523.22 6072.22 1964.9538 6468.4638 1.29 1.0653
3 1 2 -2491.73 3580.49 -2654.44 3814.0238 1.0653 1.0652
4 1 2 -96 3484.49 -102.2592 3711.7646 1.0652 1.0652
5 1 1 8471.68 11956.17 11945.0688 15656.8334 1.41 1.3095
6 1 2 -369 11587.17 -483.2055 15173.6279 1.3095 1.3095
7 2 1 1030.89 1030.89 5226.6123 5226.6123 5.07 5.07
8 2 1 314.17 1345.06 1806.4775 7033.0898 5.75 5.2288
9 2 1 239.56 1584.62 1509.228 8542.3178 6.3 5.3908
10 2 2 -554.46 1030.16 -2988.983 5553.3348 5.3908 5.3907
11 2 1 826.24 1856.4 4861.5962 10414.931 5.884 5.6103
If you are unclear about parts of the code, I can update with additional explanations.

SQL Server Spatial Query Performs Poorly at Low Zoom Levels

The following query performs very well at higher zoom levels (bounding box smaller than 2 degrees longitude by 0.5 degrees latitude, but degrades significantly as the bounding box gets larger. The table contains 7~8 million rows of text and location data stored as points in a geometry column.
I have tried different grid configurations, but the performance always degrades as the bounding box gets larger than something like #north=41.123029000000002, #east=-72.935406, #south=40.296503999999999, #west=-75.077740000000006
Any ideas? Thanks ~ Matt
I have included a table of the performance at different zoom levels.
declare #filter geometry
select #filter = GEOMETRY::STGeomFromText(
'LINESTRING(' + CONVERT(varchar,#west) + ' ' + CONVERT(varchar,#south) + ',' + CONVERT(varchar,#east) + ' ' + CONVERT(varchar,#north) + ')'
,4326
).STEnvelope();
select
x.Id
,x.[Timestamp]
,x.Location
,x.[Text]
from (
select top(1000)
t.Id
,t.[Timestamp]
,t.Location
,t.[Text]
from dbo.Table1 AS t with (nolock, index([SPIX_Table1_Location_HIGH]))
inner join containstable(
dbo.Table1
,[text]
, N'FORMSOF(INFLECTIONAL, "word1") | FORMSOF(INFLECTIONAL, "word2") | FORMSOF(INFLECTIONAL, "wordN")'
) as r on t.Id = r.[KEY]
where t.Location.Filter(#filter) = 1
AND t.[Hour] >= #HourId
order by r.[RANK] desc
) as x
order by x.[Timestamp] desc
option (maxdop 1)
Zoom Level 2 = #north=74.542308000000006,#east=94.21875,#south=-24.370607,#west=-180
Zoom Level 20 = #north=40.711250999999997,#east=-74.006050000000002,#south=40.710847000000001,#west=-74.007096000000004
This is the spatial index:
CREATE SPATIAL INDEX [SPIX_Table1_location_HIGH] ON [dbo].[Table1]
(
[location]
)USING GEOMETRY_GRID
WITH (
BOUNDING_BOX =(-180, -90, 180, 90), GRIDS =(LEVEL_1 = HIGH,LEVEL_2 = HIGH,LEVEL_3 = HIGH,LEVEL_4 = HIGH),
CELLS_PER_OBJECT = 16, FILLFACTOR = 70) ON [PRIMARY]
GO
Request Duration by Zoom Level (1000 random tests):
Level Duration0to5 Duration5to10 Duration10to15 Duration15to20 DurationGreaterThan20
2 0 0 0 0 26
3 0 0 0 0 42
4 0 0 0 0 57
5 0 0 0 0 60
6 0 0 0 0 54
7 0 0 0 1 65
8 0 2 5 6 34
9 0 3 7 10 6
10 5 23 25 14 1
11 13 26 18 3 0
12 17 31 7 0 0
13 48 11 0 0 0
14 48 6 0 0 0
15 47 1 0 0 0
16 57 0 0 0 0
17 48 8 0 0 0
18 44 3 0 0 0
19 63 5 0 0 0
20 47 3 0 0 0
ALL 437 122 62 34 345
Row counts and exec times for a typical query, w/out top(1000), forcing spatial index:
if (#level=2)
select #north=74.542308000000006,#east=94.21875,#south=-24.370607,#west=-180 --70,404 rows, 2 minutes w/ spatial
if (#level=3)
select #north=61.978465999999997,#east=-5.451886,#south=9.7052770000000006,#west=-142.56126 -- 57,911 rows, 1m22s w/ spatial
if (#level=4)
select #north=52.614061999999997,#east=-39.729228999999997,#south=26.230861999999998,#west=-108.283917 -- 45,636 rows, 1m23s w/ spatial
if (#level=5)
select #north=46.992624999999997,#east=-56.867901000000003,#south=33.775959999999998,#west=-91.145245000000003 -- 32,386 rows, 26s w/ spatial
if (#level=6)
select #north=43.934699999999999,#east=-65.437236999999996,#south=37.323439,#west=-82.575908999999996 -- 19,998 rows, 13s w/ spatial
if (#level=7)
select #north=42.343530999999999,#east=-69.721905000000007,#south=39.037540999999997,#west=-78.291240999999999 -- 11,256 rows, 13s w/ spatial
if (#level=8)
select #north=41.532438999999997,#east=-71.864238999999998,#south=39.879399999999997,#west=-76.148906999999994 -- 6,147 rows, 4s w/ spatial
if (#level=9)
select #north=41.123029000000002,#east=-72.935406,#south=40.296503999999999,#west=-75.077740000000006 -- 3,667 rows, 3s w/ spatial