偵錯 SQL 查詢結果中遺失的資料

當您的查詢傳回遺失列或欄的資料時,該怎麼辦。

您的資料遺失在哪裡?

遺失的列

在開始之前,請先確定您知道來源表格或巢狀查詢的結構描述

  1. 檢查您的來源表格或巢狀查詢是否有遺失的列。
  2. 查看下表,以查看您是否因為聯結類型而遺失列。
  3. 檢查 ON 子句中的聯結條件。例如

    -- The join condition below will filter out
    -- all transactions from the Orders table
    -- where the product category is 'Gizmo'.
    
    SELECT
        *
    FROM
        orders o
        JOIN products p ON o.product_id = p.id
            AND p.category <> 'Gizmo';
    
  4. 檢查您的 WHERE 子句是否與您的 JOIN 子句互動。例如

    -- The WHERE clause below will filter out
    -- all transactions from the Orders table
    -- where the product category is 'Gizmo'.
    
    SELECT
        *
    FROM
        orders o
        JOIN products p ON o.product_id = p.id
                       AND p.category = 'Gizmo'
    WHERE
        p.category <> 'Gizmo'
    
  5. 如果您想要新增列至您的查詢結果,以填入空白、零或 NULL 的資料,請前往如何填入遺失的報表日期資料

聯結如何篩選掉不符的列

聯結類型 如果未符合聯結條件
A INNER JOIN B 從 A 和 B 篩選掉的列。
A LEFT JOIN B 從 B 篩選掉的列。
B LEFT JOIN A 從 A 篩選掉的列。
A OUTER JOIN B 從 A 和 B 篩選掉的列。
A FULL JOIN B 未篩選掉任何列。

說明

您的 JOIN 子句中表格的順序會影響查詢傳回的列。

例如,當您撰寫 LEFT JOIN 時,查詢中 LEFT JOIN 子句之前的表格位於「左側」。如果「右側」表格(LEFT JOIN 子句之後的表格)的列不符合您在 ON 子句中的聯結條件,則會篩選掉這些列。

查詢的執行順序可能會以您可能意想不到的方式,合併您的聯結條件和 WHERE 子句。

延伸閱讀

如何填入遺失的報表日期資料

如果您的來源表格或巢狀查詢僅儲存有事件發生的日期的列,您將會取得遺失報表日期的結果。

例如,範例資料庫中的 Orders 表格僅儲存有建立訂單之日期的列。它不會儲存任何沒有訂單活動之日期的列。

-- The query below calculates the total sales
-- for each day that had at least one order.

-- For example, note that there is no row
-- in the query results for May 5, 2016.


SELECT
    DATE_TRUNC('day', o.created_at)::date AS "order_created_date",
    SUM(p.price) AS "total_sales"
FROM
    orders o
    JOIN products p ON o.product_id = p.id
WHERE
    o.created_at BETWEEN'2016-05-01'::date
    AND '2016-05-30'::date
GROUP BY
    "order_created_date"
ORDER BY
    "order_created_date" ASC;

如果您想要如下表所示的結果,您需要從具有您想要的所有日期(或任何其他序列)的表格或欄開始您的 JOIN。詢問您的資料庫管理員是否有您可以使用的表格。

+--------------------+-------------+
| report_date        | total_sales |
+--------------------+-------------+
| May 4, 2016        | 98.78       |
+--------------------+-------------+
| May 5, 2016        | 0.00        |
+--------------------+-------------+
| May 6, 2016        | 87.29       |
+--------------------+-------------+
| May 7, 2016        | 0.00        |
+--------------------+-------------+
| May 8, 2016        | 81.61       |
+--------------------+-------------+

如果您的 SQL 方言支援 GENERATE_SERIES 函式,您可以建立暫時欄來儲存您的報表日期。

-- The query below calculates the total sales
-- for every day in the report period,
-- including days with 0 orders.

-- The date_series CTE generates one row
-- per date that you want in your final result.

WITH date_series AS (
    SELECT
        *
    FROM
        GENERATE_SERIES('2016-05-01'::date, '2020-05-30'::date, '1 day'::interval) report_date
)

-- The fact_orders CTE generates the total sales
-- for each date that had an order.

, fact_orders AS (
    SELECT
        DATE_TRUNC('day', o.created_at)::date AS "order_created_date",
        SUM(p.price) AS "total_sales"
    FROM
        orders o
        JOIN products p ON o.product_id = p.id
    GROUP BY
        "order_created_date"
    ORDER BY
        "order_created_date" ASC
)

-- The main query joins the two CTEs together
-- and uses the COALESCE function to fill in the dates
-- where there were no orders (i.e. a total sales value of 0).

SELECT
    d.report_date,
    o.order_created_date,
    COALESCE(o.total_sales, 0) AS total_sales
FROM
    date_series d
    LEFT JOIN fact_orders o ON d.date = o.order_created_date
;

遺失的欄

  1. 如果您要聯結資料,請檢查您的 SELECT 陳述式是否包含您想要的欄。
    • 您是否使用正確的表格別名?
    • 您的 FROM 子句中是否遺失表格?
  2. 依照偵錯 SQL 邏輯下的步驟 1,檢查您的來源表格或查詢結果是否有遺失的欄。
  3. 深入瞭解非預期查詢結果的常見原因

您有不同的問題嗎?

您仍然遇到困難嗎?

搜尋或詢問 Metabase 社群