Row_number() 过滤后的数据

Row_number() on filtered data

我正在尝试在过滤后的数据中查找 row_number()。当我在 where 子句中包含过滤器时,row_number 会按预期工作。但是我试图在 select case 语句中添加过滤条件,但它似乎不起作用。

我不想将过滤条件放在where子句中的原因是我在同一个select sql语句中还有其他指标。我尝试使用别名 table 的子查询方法并且它有效。

但我想知道是否还有其他 better/efficient 方法可以做到这一点。

--working with where clause - works
SELECT 
  order_id,
  ROW_NUMBER() over(
    PARTITION BY orderid, date_trunc('month',order_date) 
    ORDER BY order_date) 
FROM order
WHERE order_success='yes'

--working with sub query - works
SELECT 
  order.order_id,
  row_number() over(
    PARTITION BY temp.orderid, date_trunc('month',temp.order_date)
    ORDER BY temp.order_date) 
FROM order 
LEFT OUTER JOIN (
  SELECT order_id, order_date 
  FROM order 
  WHERE order_success='yes'
) temp_order ON order.order_id=temp_order.order_id

--trying to achieve with case statement/ does not work
SELECT 
  order_id,
  CASE WHEN order_success='yes' and ROW_NUMBER() OVER(PARTITION BY  orderid, date_trunc('month',order_date) ORDER BY order_date) = 1 THEN 1 ELSE 0 END
FROM order

谢谢!

尝试将 ROW_NUMBER() 函数移动到子查询并在外部查询中将其作为别名引用:

SELECT 
  src.order_id,
  CASE 
    WHEN src.order_success='yes' AND src.MyWindowFunction = 1 THEN 1 
    ELSE 0 
  END
FROM (
  SELECT 
    order_id,
    order_success,
    ROW_NUMBER() OVER(
      PARTITION BY orderid, date_trunc('month', order_date) 
      ORDER BY order_date
    ) AS MyWindowFunction
  FROM order
) src

您需要一个 IN 子句,因为您多次获得 rownumber() 作为特定 order_id 的 1。它就像同时 order_success='yes' 对于 order_id 的单行说 x 你将通过分区获得多行作为子组因此 rownumbers 将有多个 1 并且比较会失败.

   select order_id, case when 
  order_success='yes' and row_number() 
   over(partition by 
   orderid,date_trunc('month',order_date) 
  order by order_date) IN (1) then max(1)else 
    max(0 )
    end from order

如果我没理解错的话,您只想对成功的订单进行编号,同时选择其他订单。如果是这样,您可以在分区中包含成功标志并使用 CASE WHEN 来抑制非成功行上的数字。

select
  order_id,
  case when order_success = 'yes' then
    row_number() over(partition by order_success, orderid, date_trunc('month', order_date)
                      order by order_date)
  end as num
from order 
order by order_date;

(旁注:为什么分区子句中有orderid?这不是订单table的唯一键吗?)

这取决于您是只想计算 "yes" 还是在行没有 "yes".

时希望值为 NULL

如果要统计"yes"秒,则使用累计计数:

select order_id,
       sum(case when order_success = 'yes' then 1 else 0 end) over (partition by orderid, date_trunc('month', order_date) order by order_date)
from order o;

这似乎比在非 "yes" 行上设置 NULL 值更有用。您似乎在使用 Postgres,因此可以简化为:

select order_id,
       count(*) filter (where order_success = 'yes') over (partition by orderid, date_trunc('month', order_date) order by order_date)
from order o;

如果你想在非 "yes" 行上 NULL,你可以将其中任何一个包裹在 case 表达式中。