سؤال

لقد قمت بإنشاء جدول MySQL التالي لتخزين إحداثيات Latitude / Longitude جنبا إلى جنب مع اسم لكل نقطة:

CREATE TABLE `points` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(128) NOT NULL,
  `location` point NOT NULL,
  PRIMARY KEY (`id`),
  SPATIAL KEY `location` (`location`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1;

أحاول الاستعلام عن:

  • كل النقاط داخل ن دائرة نصف قطرها ميل من نقطة معينة؛
  • مسافة كل نقطة عاد من نقطة معينة

تشير جميع الأمثلة التي وجدتها إلى استخدام مستطيل الحد الأدنى المحيط (MBR) بدلا من دائرة نصف قطرها. يحتوي الجدول على ما يقرب من مليون نقطة، لذلك يجب أن تكون هذه الحاجة فعالة قدر الإمكان.

هل كانت مفيدة؟

المحلول 2

شكرا لكم على حد سواء لإجاباتك.

في النهاية وجدت الحل في http://www.movable-type.co.uk/scripts/latlong-db.html..

نصائح أخرى

ل mysql 5.7+

بالنظر إلى أن لدينا الجدول البسيط التالي،

create table example (
  id bigint not null auto_increment primary key,
  lnglat point not null
);

create spatial index example_lnglat 
    on example (lnglat);

مع البيانات البسيطة التالية،

insert into example (lnglat) 
values
(point(-2.990435, 53.409246)),
(point(-2.990037, 53.409471)),
(point(-2.989736, 53.409676)),
(point(-2.989554, 53.409797)),
(point(-2.989350, 53.409906)),
(point(-2.989178, 53.410085)),
(point(-2.988739, 53.410309)),
(point(-2.985874, 53.412656)),
(point(-2.758019, 53.635928));

سوف تحصل على النقاط داخل مجموعة معينة من نقطة أخرى (ملاحظة: علينا البحث داخل مضلع) مع الجمع بين الوظائف التالية:

set @px = -2.990497;
set @py = 53.410943;
set @range = 150; -- meters
set @rangeKm = @range / 1000;

set @search_area = st_makeEnvelope (
  point((@px + @rangeKm / 111), (@py + @rangeKm / 111)),
  point((@px - @rangeKm / 111), (@py - @rangeKm / 111))
);

select id, 
       st_x(lnglat) lng, 
       st_y(lnglat) lat,
       st_distance_sphere(point(@px, @py), lnglat) as distance
  from example
 where st_contains(@search_area, lnglat);

يجب أن ترى شيئا من هذا القبيل نتيجة لذلك:

3   -2.989736   53.409676   149.64084252776277
4   -2.989554   53.409797   141.93232714661812
5   -2.98935    53.409906   138.11516275402533
6   -2.989178   53.410085   129.40289289527473

للإشارة إلى المسافة، إذا قمنا بإزالة القيد النتيجة لدرجة أن نقطة الاختبار تبدو وكأنها هذه:

1   -2.990435   53.409246   188.7421181457556
2   -2.990037   53.409471   166.49406509160158
3   -2.989736   53.409676   149.64084252776277
4   -2.989554   53.409797   141.93232714661812
5   -2.98935    53.409906   138.11516275402533
6   -2.989178   53.410085   129.40289289527473
7   -2.988739   53.410309   136.1875540498202
8   -2.985874   53.412656   360.78532732013963
9   -2.758019   53.635928   29360.27797292756

الملاحظة 1.: يسمى الحقل lnglat لأن هذا هو الترتيب الصحيح إذا كنت تفكر في نقاط (X، Y) وهي أيضا ترتيب معظم الوظائف (مثل نقطة) قبول المعلمة

ملاحظة 2: لا يمكنك في الواقع الاستفادة من المؤشرات المكانية إذا كنت تستخدم الدوائر؛ لاحظ أيضا أن حقل النقطة يمكن تعيينه لقبول الفهارس الخالية ولكن لا يمكن فهرس المكاني فهرسة ذلك إذا كانت هذه الحقول في الفهرس مطلوبة لتكون غير فارغة).

ملاحظة 3: يعتبر ST_BUffer (بواسطة الوثائق) لتكون سيئة لهذه حالة الاستخدام

الملاحظة 4.: يتم توثيق الوظائف أعلاه (على وجه الخصوص ST_DISTANCE_SPHERE) بأسرع وقت ولكن غير دقيق للغاية؛ إذا كانت بياناتك حساسة للغاية لتلك التي تضيف القليل من غرفة تذبذب إلى البحث والقيام ببعض ضبط الرصيد إلى مجموعة النتائج

دائرة نصف قطرها ليست فهرسة بكفاءة. يجب عليك استخدام المستطيل المحيطي للحصول بسرعة على النقاط التي ربما تبحث عنها، ثم تصفية نقاط خارج دائرة نصف قطرها.

فعلت ذلك لنقطة واحدة داخل الدائرة مع دائرة نصف قطرها

SELECT 
    *
FROM 
    `locator`
WHERE
    SQRT(POW(X(`center`) - 49.843317 , 2) + POW(Y(`center`) - 24.026642, 2)) * 100 < `radius`

التفاصيل ومزيد من استعلام عينة هنا هنا http://dexxtr.com/post/83498801191/how-to-determine-point-inside-circle-using-mysql., ، أتمنى أن يساعدك هذا

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top