调试 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 社区

这有帮助吗?

感谢您的反馈!
订阅新闻通讯
Metabase 的更新和新闻
© . This site is unofficial and not affiliated with Metabase, Inc.