簡體   English   中英

使用JOIN或帶有臨時表的相關子查詢進行MySQL查找

[英]MySQL lookup using JOIN or correlated subquery with TEMPORARY TABLE

我有兩個主表, providers' and depots。 每個提供者都有強制性的第一地點。 通過添加其他“倉庫”來提供其他位置。 “ etc”表示與提供商帳戶相關的大量其他var。 為了簡化起見,此處省略了多余的表格信息和過濾器。

providers
+--------+------------+-----+
| id     | location   | etc |
+--------+------------+-----+
| 1      | POINT(1,1) | ... |
| 2      | POINT(1,2) | ... |
| 3      | POINT(1,3) | ... |
+--------+------------+-----+

depots
+---------+------------+------------+
| depotId | providerId | location   |
+---------+------------+------------+
| 1       | 1          | POINT(2,1) |
| 2       | 1          | POINT(2,2) |
| 3       | 1          | POINT(2,3) |
| 4       | 2          | POINT(2,4) |
| 5       | 2          | POINT(2,5) |
+---------+------------+------------+

提供者可能有零個或多個額外的倉庫。 這些“位置”用於計算每個提供者到來的“工作”的距離。 傳統上我使用UNION加盟providersdepots表,形成一個單一的表,我將其稱為provDeps

SELECT id,location,0來自提供者的AS depotId UNION SELECT p.id,d.location d.id AS來自提供者p,depot的depotId

讓我們假設這是一個視圖,目前為止沒有效率和索引。 希望它將減少查詢的視覺復雜性。

provDeps
+--------+------------+---------+-----+
| id     | location   | depotId | etc |
+--------+------------+---------+-----+
| 1      | POINT(1,1) | 0       | ... |
| 1      | POINT(2,1) | 1       | ... |
| 1      | POINT(2,2) | 2       | ... |
| 1      | POINT(2,3) | 3       | ... |
| 2      | POINT(1,2) | 0       | ... |
| 2      | POINT(2,4) | 4       | ... |
| 2      | POINT(2,5) | 5       | ... |
| 3      | POINT(1,3) | 0       | ... |
+--------+------------+---------+-----+

然后,我使用provDeps執行其他查找。 這里的想法是計算作業到每個倉庫的距離。 這是通過存儲過程執行的。

SELECT loc.*, degToMeter(st_distance(jobLocation, location)) AS distanceToJob FROM provDeps;

+--------+------------+---------+---------------+-----+
| id     | location   | depotId | distanceToJob | etc |
+--------+------------+---------+---------------+-----+
| 1      | POINT(1,1) | 0       | 8234          | ... |
| 1      | POINT(2,1) | 1       | 7334          | ... |
| 1      | POINT(2,2) | 2       | 6434          | ... |
| 1      | POINT(2,3) | 3       | 5534          | ... |
| 2      | POINT(1,2) | 0       | 4634          | ... |
| 2      | POINT(2,4) | 4       | 3734          | ... |
| 2      | POINT(2,5) | 5       | 2834          | ... |
| 3      | POINT(1,3) | 0       | 1934          | ... |
+--------+------------+---------+---------------+-----+

現在,我需要減少此列表,僅保留按提供者ID分組的最近的軟件倉庫。 結果將包括每個提供程序,但每個提供程序都只有一個軟件倉庫-主要位置,軟件倉庫“ 0”或最近的軟件倉庫的ID。 這是期望的結果:

+--------+------------+---------+---------------+-----+
| id     | location   | depotId | distanceToJob | etc |
+--------+------------+---------+---------------+-----+
| 1      | POINT(2,3) | 3       | 5534          | ... |
| 2      | POINT(2,5) | 5       | 2834          | ... |
| 3      | POINT(1,3) | 0       | 1934          | ... |
+--------+------------+---------+---------------+-----+

我嘗試了多種方法,但是每種方法都遇到了不同的問題。 我最接近成功的方法是使用臨時表:-

DROP TEMPORARY TABLE IF EXISTS locTemp;
CREATE TEMPORARY TABLE locTemp AS
    SELECT depots.*, st_distance(jobLocation, location) AS distanceToJob
    FROM provDeps

然后,我嘗試使用相關的子查詢,但這會產生一次嘗試在單個查找中兩次訪問臨時表的錯誤:-

SELECT * FROM locTemp
WHERE distanceToJob = (SELECT MIN(distanceToJob) FROM locTemp AS lt WHERE lt.id = locTemp.id);

這將導致錯誤“無法重新打開表:'locTemp'”。 我也嘗試過執行聯接,但是隨后從子查詢中出現分組錯誤,或者無法訪問臨時表本身:-

SELECT * FROM
(
    SELECT id, depotId, MIN(distanceToJob) as minDist
    FROM locTemp GROUP BY id
) AS res
INNER JOIN locTemp AS lt on lt.id = res.id and lt.minDist = res.distanceToJob;

任何指針,或更好的解決方案,將不勝感激! :)

我認為您不一定需要在此處使用臨時表或視圖。 您的最終查詢在這里看起來完全正確,我已在下面對其進行了修改。 我看到的唯一問題是您使用GROUP BY選擇了一個非聚合列,也許使用臨時表存在問題。

SELECT
    t1.id, t1.location, t1.depotId,
    degToMeter(st_distance(t1.jobLocation, t1.location)) AS distanceToJob
FROM provDeps t1
INNER JOIN
(
    SELECT
        id,
        MIN(degToMeter(st_distance(t1.jobLocation, t1.location))) AS minDistanceToJob
    FROM provDeps
    GROUP BY id
) t2
    ON t1.id = t2.id AND
       degToMeter(st_distance(t1.jobLocation, t1.location)) = t2.minDistanceToJob;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM