偵錯 SQL 查詢結果中遺失的資料
當您的查詢傳回遺失列或欄的資料時,該怎麼辦。
您的資料遺失在哪裡?
遺失的列
在開始之前,請先確定您知道來源表格或巢狀查詢的結構描述。
- 檢查您的來源表格或巢狀查詢是否有遺失的列。
- 查看下表,以查看您是否因為聯結類型而遺失列。
-
檢查
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';
-
檢查您的
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'
- 如果您想要新增列至您的查詢結果,以填入空白、零或
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
;
遺失的欄
- 如果您要聯結資料,請檢查您的
SELECT
陳述式是否包含您想要的欄。- 您是否使用正確的表格別名?
- 您的
FROM
子句中是否遺失表格?
- 依照偵錯 SQL 邏輯下的步驟 1,檢查您的來源表格或查詢結果是否有遺失的欄。
- 深入瞭解非預期查詢結果的常見原因。
您有不同的問題嗎?
您仍然遇到困難嗎?
搜尋或詢問 Metabase 社群。