簡體   English   中英

MySQL選擇最大值而不使用子查詢

[英]MySQL select max value without subquery

關於此主題這里有很多問題(請參閱此處此處的示例),但是我無法弄清楚如何正確運行我的特定案例。

這是SQLFiddle ,其中包含表架構,記錄和查詢。 目前,我有一個有效的查詢,但是效率很低,因為它使用了一個依賴子查詢:

SELECT 
      id_document, version, id_plant_mov, id_production_type, is_ext, 
      id_cost_center, id_import_kpi_code, id_plant_tag, value 
FROM  document_production_history2 
WHERE id_document = 751 
  AND id_production_type IN (1, 3) 
  AND is_group_production = 0 
  AND (id_document, id_plant_mov, id_production_type, id_cost_center, 
       id_import_kpi_code, id_plant_tag, is_ext, version) 
      IN (
        SELECT id_document, id_plant_mov, id_production_type, 
               id_cost_center, id_import_kpi_code, id_plant_tag, is_ext, 
               MAX(version) 
        FROM document_production_history2 
        GROUP BY id_document, id_plant_mov, id_production_type, 
            id_cost_center, id_import_kpi_code, id_plant_tag, is_ext);

我試圖這樣重寫上面的查詢:

SELECT d.id_document id_doc, d.version, d.id_plant_mov, 
    d.id_production_type id_prod_type, d.is_ext, d.id_cost_center, 
    d.id_import_kpi_code kpi_code, d.id_plant_tag, d.value 
FROM document_production_history2 d 
JOIN (
  SELECT id_document, id_plant_mov, id_production_type, is_ext, 
      id_cost_center, id_import_kpi_code, id_plant_tag, 
      is_group_production, MAX(version) version 
  FROM document_production_history2 
  WHERE id_document = 751 
  AND id_production_type IN (1, 3) 
  AND is_group_production = 0 
  GROUP BY id_document, id_plant_mov, id_production_type, 
      id_cost_center, id_import_kpi_code, id_plant_tag, 
      is_group_production
) m 
ON d.version = m.version 
AND d.id_document = m.id_document 
AND d.id_production_type = m.id_production_type 
AND d.id_plant_mov = m.id_plant_mov 
AND d.id_plant_tag = m.id_plant_tag 
AND d.id_cost_center = m.id_cost_center 
AND d.id_import_kpi_code = m.id_import_kpi_code 
AND d.is_ext = m.is_ext 
AND d.is_group_production = m.is_group_production;

但它返回27行,而不是預期的10行。

提前致謝。

派生表是到達此處的方法。 在第二個示例中,您的問題是返回的每一行都獲得了max(version),包括is_group_production中的差異-這是多余的行潛入的地方。因此,where子句因此需要留在外部查詢中。 從理論上講,您可以將where子句的其他兩個部分移至內部查詢,但是我發現這相當不易理解和不直觀。

這將返回10行:

SELECT 
      d.id_document, d.version, d.id_plant_mov, d.id_production_type, d.is_ext, 
      d.id_cost_center, d.id_import_kpi_code, d.id_plant_tag, d.value 
FROM  
      document_production_history2  d JOIN

(SELECT id_document, id_plant_mov, id_production_type, 
       id_cost_center, id_import_kpi_code, id_plant_tag, is_ext, 
       MAX(VERSION) AS maxversion
 FROM document_production_history2 
 GROUP BY id_document, id_plant_mov, id_production_type, 
    id_cost_center, id_import_kpi_code, id_plant_tag, is_ext) m ON

  d.version = m.maxversion and 
  d.id_document = m.id_document and
  d.id_production_type = m.id_production_type  and
  d.id_plant_mov = m.id_plant_mov  and
  d.id_plant_tag = m.id_plant_tag  and
  d.id_cost_center = m.id_cost_center and 
  d.id_import_kpi_code = m.id_import_kpi_code and
  d.is_ext = m.is_ext 

WHERE 
  d.id_document = 751  and
  d.id_production_type IN (1, 3)  and
  d.is_group_production = 0 

據我所知,它的表現還不錯。 派生表不是理想的解決方案,但是它們比子查詢好一個數量級,因為mysql不必對結果集的每一行都執行它們。

這是一個JOIN ,相當於您的第一個查詢。 您需要從子查詢中取出is_group_production = 0 ,並且僅在主查詢中執行。 這會濾除最大版本為分組生產的行。

SELECT d.id_document id_doc, d.version, d.id_plant_mov, 
    d.id_production_type id_prod_type, d.is_ext, d.id_cost_center, 
    d.id_import_kpi_code kpi_code, d.id_plant_tag, d.value 
FROM document_production_history2 d 
JOIN (
  SELECT id_document, id_plant_mov, id_production_type, is_ext, 
      id_cost_center, id_import_kpi_code, id_plant_tag, 
      MAX(version) version 
  FROM document_production_history2 
  WHERE id_document = 751 
  AND id_production_type IN (1, 3) 
  GROUP BY id_document, id_plant_mov, id_production_type, 
      id_cost_center, id_import_kpi_code, id_plant_tag

) m 
ON d.version = m.version 
AND d.id_document = m.id_document 
AND d.id_production_type = m.id_production_type 
AND d.id_plant_mov = m.id_plant_mov 
AND d.id_plant_tag = m.id_plant_tag 
AND d.id_cost_center = m.id_cost_center 
AND d.id_import_kpi_code = m.id_import_kpi_code 
AND d.is_ext = m.is_ext 
WHERE d.is_group_production = 0;

DEMO

這個:

JOIN (
    SELECT id_document, id_plant_mov, id_production_type, is_ext, 
      id_cost_center, id_import_kpi_code, id_plant_tag, 
      is_group_production, MAX(version) version 
    FROM document_production_history2 
    WHERE id_document = 751 
    AND id_production_type IN (1, 3) 
    AND is_group_production = 0 
    GROUP BY id_document, id_plant_mov, id_production_type, 
      id_cost_center, id_import_kpi_code, id_plant_tag, 
      is_group_production
) m 

應該是這樣的:

JOIN (
    SELECT id_document, MAX(version) version 
    FROM document_production_history2 
    WHERE id_document = 751 
    AND id_production_type IN (1, 3) 
    AND is_group_production = 0 
    GROUP BY id_document
) m 

加入m時,僅使用id_document和version。

為什么不完全刪除子查詢?

SELECT 
id_document, version, id_plant_mov, id_production_type, is_ext, 
id_cost_center, id_import_kpi_code, id_plant_tag, value, MAX(version) 
FROM  document_production_history2 
WHERE id_document = 751 
AND id_production_type IN (1, 3) 
AND is_group_production = 0
GROUP BY id_document, id_plant_mov, id_production_type, id_cost_center, id_import_kpi_code, id_plant_tag, is_ext

暫無
暫無

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

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