【问题标题】:PostgreSQL - get records with null valuesPostgreSQL - 获取具有空值的记录
【发布时间】:2012-09-17 12:20:22
【问题描述】:

我正在尝试获取一个查询,该查询将显示 90 天内没有销售任何东西的分销商,但我遇到的问题是 NULL 值。似乎 PostgreSQL 忽略了 null 值,即使我查询显示它(或者我可能以错误的方式做)。

假设有 1000 个分销商,但是通过这个查询我只得到 1 个分销商,但应该有更多没有销售任何东西的分销商,因为如果我编写 SQL 查询来显示最近销售任何数量的分销商90 天,它显示大约 500。所以我想知道其他 499 在哪里?如果我理解正确,其他 499 没有任何销售,所以所有记录都是空的,并且不会在查询中显示。

有谁知道如何让它显示一个表的空值,而另一个表不为空? (比如合作伙伴表(res_partner)不为空,但sale_order表(销售)或对象为空?(我也尝试像so.id IS NULL一样过滤,但这样我得到空查询)

我的查询代码:

(
SELECT
    min(f1.id) as id,
    f1.partner as partner,
    f1.sum1
       FROM
    (
       SELECT
          min(f2.id) as id,
          f2.partner as partner,
          sum(f2.null_sum) as sum1
       FROM
    (
    SELECT
          min(rp.id) as id,
          rp.search_name as partner,
     CASE
       WHEN
             sol.price_subtotal IS NULL
       THEN
             0
       ELSE
             sol.price_subtotal
     END as null_sum
    FROM
          sale_order as so,
          sale_order_line as sol,
          res_partner as rp
    WHERE
    sol.order_id=so.id and
    so.partner_id=rp.id
    and
    rp.distributor=TRUE
    and
    so.date_order <= now()::timestamp::date
    and
    so.date_order >= date_trunc('day', now() - '90 day'::interval)::timestamp::date
    and 
    rp.contract_date <= date_trunc('day', now() - '90 day'::interval)::timestamp::date
    GROUP BY
    partner,
    null_sum
   )as f2
   GROUP BY
   partner
  ) as f1
WHERE
sum1=0
GROUP BY
partner,
sum1
)as fld

编辑:2012-09-18 上午 11 点。

我想我明白为什么 Postgresql 会这样。这是因为时间间隔。它检查该 inverval 中是否有任何非空值。所以它只找到了一条记录,因为该记录的销售订单为零(它没有从 null 转换为零),而检查 null 值的部分只是被跳过了。如果我删除时间间隔,那么我会看到所有根本不卖任何东西的分销商。但是由于某种原因,它会停止检查空值并查看是否只有空值。

那么有谁知道如何让它在给定的时间间隔内也检查空值?..(准确地说是过去 90 天)

【问题讨论】:

  • 你能给出create table语句吗?我正在考虑外部连接查询...
  • 这不是您发布的有效 SQL 语句。

标签: postgresql


【解决方案1】:

sum()min() 这样的聚合会忽略 NULL 值。这是 SQL 标准所要求的,我所知道的每个 DBMS 都具有这样的行为。

如果您想将 NULL 值视为例如一个零,然后使用这样的东西:

sum(coalesce(f2.null_sum, 0)) as sum1

但据我了解,您的问题和无效查询实际上希望在 res_partner 和 sales 表之间建立外部联接。

类似这样的:

SELECT min(rp.id) as id,
       rp.search_name as partner,
       sum(coalesce(sol.price_subtotal,0)) as price_subtotal
FROM res_partner as rp 
  LEFT JOIN sale_order as so ON so.partner_id=rp.id and rp.distributor=TRUE
  LEFT JOIN sale_order_line as sol ON sol.order_id=so.id 
WHERE so.date_order <= CURRENT_DATE
  and so.date_order >= date_trunc('day', now() - '90 day'::interval)::timestamp::date
  and rp.contract_date <= date_trunc('day', now() - '90 day'::interval)::timestamp::date
GROUP BY rp.search_name

我不能 100% 确定我正确理解了您的问题,但它可能会给您一个先机。

【讨论】:

  • 我的解决方案结果相同。数据库可能有问题..当我将间隔更改为 1 天时,它如何无法显示任何结果?但它显示时间间隔较大(90 天)。应该有比过去 90 天没有销售任何东西的分销商多得多,但它没有显示任何昨天没有销售的分销商,但它显示了一个在过去 90 天内没有销售的分销商。这很奇怪。
  • @oerp:如果不向我们展示一些示例数据和您正在运行的 真实 语句,就无法判断您那边出了什么问题。
  • 好的。如果我使用你的建议,我会得到 247 条记录(一条总和为零)。如果我添加 WHERE sum1=0,我会得到 1 条总和为零的记录。我将so.date_order &gt;= date_trunc('day', now() - '90 day'::interval)::timestamp::date 此处的 90 更改为 1,我没有得到任何记录。如果我将间隔保留为一天,但删除 sum1=0,我会得到 23 条记录(并且没有一条总和为零)。如果我只是编写 SQL 查询来显示 rp.search_name WHERE rp.distributor=TRUE and rp.contract_date &lt;= date_trunc('day', now() - '90 day'::interval)::timestamp::date 我会得到 529 条记录。
  • 所以大约有一半的记录由于未知原因没有显示(至少我不知道为什么)
  • 我在想,我开始想知道,postgresql 如何在特定时间定义值何时为空?当它检查 90 天时,假设一天有多少空值?.. 为什么我想知道这一点,是因为如果某些合作伙伴(销售订单)的一列为空,而合作伙伴列不是(总是不为空,因为它忽略了空值),如果给定的合作伙伴有的话,每天有多少个“零”?..所以也许有一种方法可以将合作伙伴的销售总和设置为零,如果没有任何销售订单(对于那些分销商/合作伙伴,该列在 90 天内为空)?
【解决方案2】:

尝试命名子查询,并使用 col.q1、col.q2 等检索它们的列,以确保您正在处理哪个查询/子查询中的哪一列。也许它有点简单,例如它将一些仅包含 NULL 的行合并为一行?此外,至少出于调试目的,在每个查询/子查询的末尾添加 , count(*) 以获取结果返回的隐式行数是明智的。很难猜测到底发生了什么......

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-16
    • 1970-01-01
    • 2016-11-06
    • 2016-06-08
    • 1970-01-01
    相关资源
    最近更新 更多