Home » SQL & PL/SQL » SQL & PL/SQL » SQL query to calculate distance and update (Oracle 11.2.0.3)
SQL query to calculate distance and update [message #630223] Tue, 23 December 2014 05:06 Go to next message
pointers
Messages: 451
Registered: May 2008
Senior Member
Hi,

I have two tables having millions of rows in each table i.e. t_src_dim and t_trgt_dim.

t_src_dim stores name of the car owner and his location in terms of latitude and longitude.
t_trgt_dim stores latitude and longitude of the service center.

Now the task is, for each record in t_src_dim, identify the nearest service center from t_trgt_dim using lat, lon columns of both the tables
and update the t_src_dim tabl.flag to 'Y' if any service center is in the limit of 20 miles and update it to 'N' if there is no service center in the limit of 20 miles.

function msr_dstnc calculates (just for e.g.) the distance in miles for given set of latitude and longitude.

create table t_src_dim (owner varchar2(20), lat number, lon number, flag  varchar2(20))
/

begin
insert into t_src_dim values ('a',1, 2,'');
insert into t_src_dim values ('b',1, 0,'');
insert into t_src_dim values ('c',1, 5,'');
insert into t_src_dim values ('d',4, 6,'');
insert into t_src_dim values ('e',8, 4,'');
insert into t_src_dim values ('f',9, 4,'');
insert into t_src_dim values ('g',1, 1,'');
end;
/

create table t_trgt_dim (service_center varchar2(40), lat number, lon number)
/

begin
insert into t_trgt_dim values ('carz',5, 1);
insert into t_trgt_dim values ('cars heaven',1,2 );
insert into t_trgt_dim values ('your car',1, 2);
insert into t_trgt_dim values ('yourcar center',1, 2);
insert into t_trgt_dim values ('abcd',1, 1);
insert into t_trgt_dim values ('new car center',1, 1);
end;
/

CREATE OR REPLACE function msr_dstnc(a number, b number, c number, d number)
return number
as
begin
return a*b*c*d;
end;
/

Below query is serving the purpose but I would like to know if there is a better way doing it interms of performance.

I would like to stop processing of the row from the t_src_dim table once any row from t_trgt_dim is found in the distance of 20 miles, I've thought in PLSQL but is it possible in SQL.

UPDATE t_src_dim a
   SET flag =
          (SELECT flg
             FROM (SELECT   a.lat, a.lon,
                            MAX (CASE
                                    WHEN msr_dstnc (a.lat, a.lon, b.lat, b.lon) < 20
                                       THEN 'Y'
                                    ELSE 'N'
                                 END
                                ) flg
                       FROM t_src_dim a, t_trgt_dim b
                   GROUP BY a.lat, a.lon) t
            WHERE t.lat = a.lat AND t.lon = a.lon)



Regards,
Pointers

[Updated on: Tue, 23 December 2014 05:08]

Report message to a moderator

Re: SQL query to calculate distance and update [message #630230 is a reply to message #630223] Tue, 23 December 2014 06:33 Go to previous messageGo to next message
Michel Cadot
Messages: 68647
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

Buy "Spatial" option, it is made for this.
If you don't want, the first thing is to get rid of your custom function, there is no need of it.

Re: SQL query to calculate distance and update [message #630233 is a reply to message #630230] Tue, 23 December 2014 06:39 Go to previous messageGo to next message
pointers
Messages: 451
Registered: May 2008
Senior Member
Hi Micheal,

Thank you for your response.

I am not sure if our client can take the option of buying something.
However, the function which I am using is a sample function, in fact, the actual function is bit more complex in logic therefore I used the function to cover-up the code and its used in other areas as well.


Regards,
Pointers
Re: SQL query to calculate distance and update [message #630241 is a reply to message #630233] Tue, 23 December 2014 07:59 Go to previous messageGo to next message
Michel Cadot
Messages: 68647
Registered: March 2007
Location: Nanterre, France, http://...
Senior Member
Account Moderator

However this is the way to increase the performances and it is worth you give it a try.

Re: SQL query to calculate distance and update [message #630249 is a reply to message #630223] Tue, 23 December 2014 12:03 Go to previous messageGo to next message
Solomon Yakobson
Messages: 3273
Registered: January 2010
Location: Connecticut, USA
Senior Member
Scrap your function as Michel suggested. Get rid of group by. Compare:

explain plan for
UPDATE t_src_dim a
   SET flag =
          (SELECT flg
             FROM (SELECT   a.lat, a.lon,
                            MAX (CASE
                                    WHEN a.lat * a.lon * b.lat * b.lon < 20
                                       THEN 'Y'
                                    ELSE 'N'
                                 END
                                ) flg
                       FROM t_src_dim a, t_trgt_dim b
                   GROUP BY a.lat, a.lon) t
            WHERE t.lat = a.lat AND t.lon = a.lon)
/
select * from table(dbms_xplan.display)
/

PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------
Plan hash value: 2591588453

--------------------------------------------------------------------------------------
| Id  | Operation               | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT        |            |     7 |   266 |    52  (14)| 00:00:01 |
|   1 |  UPDATE                 | T_SRC_DIM  |       |       |            |          |
|   2 |   TABLE ACCESS FULL     | T_SRC_DIM  |     7 |   266 |     3   (0)| 00:00:01 |
|   3 |   VIEW                  |            |     1 |    29 |     6   (0)| 00:00:01 |
|   4 |    SORT GROUP BY        |            |     1 |    52 |     6   (0)| 00:00:01 |
|   5 |     MERGE JOIN CARTESIAN|            |     1 |    52 |     6   (0)| 00:00:01 |

PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------
|*  6 |      TABLE ACCESS FULL  | T_SRC_DIM  |     1 |    26 |     3   (0)| 00:00:01 |
|   7 |      BUFFER SORT        |            |     6 |   156 |     3   (0)| 00:00:01 |
|   8 |       TABLE ACCESS FULL | T_TRGT_DIM |     6 |   156 |     3   (0)| 00:00:01 |
--------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   6 - filter("A"."LAT"=:B1 AND "A"."LON"=:B2)

Note

PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------------
-----
   - dynamic sampling used for this statement (level=2)

24 rows selected.

SQL> 


and

explain plan for
UPDATE t_src_dim a
   SET flag = CASE
                WHEN EXISTS (SELECT 1 FROM t_trgt_dim b WHERE b.lat * b.lon * a.lon * b.lat < 20) THEN 'Y'
                ELSE 'N'
              END
/

select * from table(dbms_xplan.display)
/

PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------
Plan hash value: 244025122

---------------------------------------------------------------------------------
| Id  | Operation          | Name       | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT   |            |     7 |   175 |    31  (23)| 00:00:01 |
|   1 |  UPDATE            | T_SRC_DIM  |       |       |            |          |
|   2 |   TABLE ACCESS FULL| T_SRC_DIM  |     7 |   175 |     3   (0)| 00:00:01 |
|*  3 |   TABLE ACCESS FULL| T_TRGT_DIM |     1 |    26 |     3   (0)| 00:00:01 |
---------------------------------------------------------------------------------


PLAN_TABLE_OUTPUT
---------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------

   3 - filter("B"."LAT"*"B"."LON"*:B1*"B"."LAT"<20)

Note
-----
   - dynamic sampling used for this statement (level=2)

19 rows selected.

SQL>  


And you can improve it even more by creating FBI on t_trgt_dim:

SQL> create index t_trgt_dim_idx1
  2    on t_trgt_dim(
  3                  lon * lat
  4                 )
  5  /

Index created.

SQL> explain plan for
  2  UPDATE t_src_dim a
  3     SET flag = CASE
  4                  WHEN a.lat * a.lon = 0 then 'Y'
  5                  WHEN EXISTS (SELECT 1 FROM t_trgt_dim b WHERE b.lat * b.lon < 20 / a.lon * a.lat) THEN 'Y'
  6                  ELSE 'N'
  7                END
  8  /

Explained.

SQL> select * from table(dbms_xplan.display)
  2  /

PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------------
Plan hash value: 1366157097

--------------------------------------------------------------------------------------
| Id  | Operation          | Name            | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | UPDATE STATEMENT   |                 |     7 |   266 |    17  (42)| 00:00:01 |
|   1 |  UPDATE            | T_SRC_DIM       |       |       |            |          |
|   2 |   TABLE ACCESS FULL| T_SRC_DIM       |     7 |   266 |     3   (0)| 00:00:01 |
|*  3 |   INDEX RANGE SCAN | T_TRGT_DIM_IDX1 |     1 |    13 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------


PLAN_TABLE_OUTPUT
-----------------------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------

   3 - access("LON"*"LAT"<20/:B1*:B2)

Note
-----
   - dynamic sampling used for this statement (level=2)

19 rows selected.

SQL> 


SY.
Re: SQL query to calculate distance and update [message #630331 is a reply to message #630249] Wed, 24 December 2014 10:15 Go to previous messageGo to next message
andrew again
Messages: 2577
Registered: March 2000
Senior Member
you really need a tool like Alteryx to create drive-time maps rather than distance based measure. Something like this http://resources.arcgis.com/en/help/getting-started/articles/GUID-827E65AE-12B7-4B6D-B1EB-0F6037031573-web.png
Re: SQL query to calculate distance and update [message #630484 is a reply to message #630223] Mon, 29 December 2014 04:10 Go to previous message
pointers
Messages: 451
Registered: May 2008
Senior Member
Thank you for your time.
Special thanks to Solomon, I think your solution was superb, it worked well with us.

Thank you very much.

Regards,
Pointers
Previous Topic: How to display a record from an array(nested table)
Next Topic: LONG to VARCHAR2 conversion using dblink
Goto Forum:
  


Current Time: Fri Apr 26 19:43:49 CDT 2024