سؤال

بالنظر إلى وظيفة zipdistance(zipfrom,zipto) التي تحسب المسافة (بالأميال) بين رمزين بريديين والجداول التالية:

create table zips_required(
   zip varchar2(5)
);

create table zips_available(
   zip varchar2(5),
   locations number(100)
);

كيف يمكنني إنشاء استعلام يعيد لي كل رمز بريدي من الجدول zips_required والحد الأدنى للمسافة التي قد تنتج مجموعًا (مواقع) >= n.

حتى الآن قمنا بتشغيل استعلام حلقة شاملة لكل نصف قطر حتى نحقق المعايير.

--Do this over and over incrementing the radius until the minimum requirement is met
select count(locations) 
from zips_required zr 
left join zips_available za on (zipdistance(zr.zip,za.zip)< 2) -- Where 2 is the radius

قد يستغرق هذا بعض الوقت على قائمة كبيرة.يبدو أنه يمكن القيام بذلك باستخدام استعلام تحليلي أوراكل على غرار:

min() over (
  partition by zips_required.zip 
  order by zipdistance( zips_required.zip, zips_available.zip)
  --range stuff here?
) 

الاستعلامات التحليلية الوحيدة التي قمت بها كانت تعتمد على "رقم الصف (التقسيم حسب الترتيب)"، وأنا أسير في مناطق غير معروفة بهذا.أي توجيه في هذا الشأن هو موضع تقدير كبير.

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

المحلول

هذا هو ما خطرت لي :

SELECT zr, min_distance
  FROM (SELECT zr, min_distance, cnt, 
               row_number() over(PARTITION BY zr ORDER BY min_distance) rnk
           FROM (SELECT zr.zip zr, zipdistance(zr.zip, za.zip) min_distance,
                         COUNT(za.locations) over(
                             PARTITION BY zr.zip 
                             ORDER BY zipdistance(zr.zip, za.zip)
                         ) cnt
                    FROM zips_required zr
                   CROSS JOIN zips_available za)
          WHERE cnt >= :N)
 WHERE rnk = 1
  1. لكل zip_required حساب المسافة إلى zip_available وفرزها حسب المسافة
  2. لكل zip_required ال count مع range يسمح لك بمعرفة كم zip_availables تقع في دائرة نصف قطرها تلك المسافة.
  3. عامل التصفية (أولاً حيث COUNT(locations) > N)

اعتدت على إنشاء بيانات العينة:

INSERT INTO zips_required
   SELECT to_char(10000 + 100 * ROWNUM) FROM dual CONNECT BY LEVEL <= 5;

INSERT INTO zips_available
   (SELECT to_number(zip) + 10 * r, 100 - 10 * r FROM zips_required, (SELECT ROWNUM r FROM dual CONNECT BY LEVEL <= 9));

CREATE OR REPLACE FUNCTION zipdistance(zipfrom VARCHAR2,zipto VARCHAR2) RETURN NUMBER IS
BEGIN
   RETURN abs(to_number(zipfrom) - to_number(zipto));
END zipdistance;
/

ملحوظة: لقد استخدمت COUNT(locations) وSUM(locations) في سؤالك، وافترضت أنه COUNT(locations)

نصائح أخرى

SELECT  *
FROM    (
        SELECT  zip, zd, ROW_NUMBER() OVER (PARTITION BY zip ORDER BY rn DESC) AS rn2
        FROM    (
                SELECT  zip, zd, ROW_NUMBER() OVER (PARTITION BY zip ORDER BY zd DESC) AS rn
                FROM    (
                        SELECT  zr.zip, zipdistance(zr.zip, za.zip) AS zd
                        FROM    zips_required zr
                        JOIN    zips_available za
                        )
                )
        WHERE   rn <= n
        )
WHERE   rn2 = 1

لكل zip_required، وهذا سوف تحديد المسافة الحد الأدنى إلى التي تناسب في N zip_available، أو المسافة القصوى إذا كان عدد zip_available هو أقل من N.

وأنا حل نفس المشكلة عن طريق إنشاء مجموعة فرعية من ZIP داخل دائرة نصف قطرها متر مربع من الرمز البريدي معين (سهلة الرياضيات: <أو> بذور النيم نصف القطر)، ثم بالتكرار عبر كل دخول في فرعية لمعرفة ما إذا كان داخل دائرة نصف قطرها اللازمة . عملت مثل سحر وكان سريع جدا.

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

ملحوظة:ومع ذلك، سيوفر هذا مسافات تقريبية، لذلك يمكن للمرء استخدام هذا وفقًا لذلك.بمجرد إنشاء الفوائد بسرعة فائقة لجلب النتائج.

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