نقاط الاستعلام داخل دائرة نصف قطرها معينة في MySQL
-
18-09-2019 - |
سؤال
لقد قمت بإنشاء جدول 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., ، أتمنى أن يساعدك هذا