You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何创建关联视图获取同一客户同商品的上一个InvoicePosition?

实现方案:带历史记录的发票行视图

现有表结构

create table Article (
  ID int generated by default as identity primary key, 
  Name text);
create table Client (
  ID int generated by default as identity primary key, 
  Name text);
create table Invoice (
  ID int generated by default as identity primary key, 
  Date date, 
  Client int references client(id));
create table InvoicePosition (
  ID int generated by default as identity primary key, 
  Invoice int references invoice(id), 
  Article int references article(id), 
  Quantity numeric, 
  Price numeric,
  constraint each_invoice_can_only_contain_one_invoiceposition_for_each_article
    unique (Invoice,Article));

示例数据

insert into article(id,name) values
  (1,'article1'),
  (2,'article2'),
  (3,'article3');
insert into client(id,name) values
  (1,'client1'),
  (2,'client2'),
  (3,'client3');
insert into invoice(id,date,client) values
  (1,'yesterday',1),    -- 客户1的发票
  (2,'today',1),        -- 客户1的发票
  (3,'tomorrow',1),     -- 客户1的发票
  (4,'yesterday', 2);   -- 客户2的发票
insert into InvoicePosition values
  (1,1,1,11.0,77.0),    -- 客户1昨日发票的商品1
  (2,1,2,22.0,88.0),    -- 客户1昨日发票的商品2
  (3,1,3,33.0,99.0),    -- 客户1昨日发票的商品3
  (4,2,1,12.0,78.0),    -- 客户1今日发票的商品1
  (5,2,2,23.0,89.0),    -- 客户1今日发票的商品2
  (6,4,1,34.0,100.0);   -- 客户2昨日发票的商品1

需求说明

查询InvoicePosition时,需附带同一客户、同一商品的最近历史发票行,满足以下条件:

  • 历史发票行的商品ID与当前行一致
  • 历史发票所属客户与当前行所属客户一致
  • 历史发票的日期早于当前发票的日期
  • 仅取日期最近的那一条历史记录

目标是创建视图,支持后续用WHERE子句筛选特定发票的所有行(含对应历史记录)。

实现视图的SQL

利用PostgreSQL的LATERAL JOIN搭配排序和限制,精准获取最近的历史记录:

CREATE OR REPLACE VIEW InvoicePosView AS
SELECT
  ip.ID AS InvoicePosId,
  ip.Invoice AS InvoiceId,
  ip.Article AS ArticleID,
  ip.Quantity,
  ip.Price,
  prev_ip.ID AS LastInvoicePosId
FROM InvoicePosition ip
JOIN Invoice inv ON ip.Invoice = inv.ID
LEFT JOIN LATERAL (
  SELECT ip_prev.ID
  FROM InvoicePosition ip_prev
  JOIN Invoice inv_prev ON ip_prev.Invoice = inv_prev.ID
  WHERE
    ip_prev.Article = ip.Article
    AND inv_prev.Client = inv.Client
    AND inv_prev.Date < inv.Date
  ORDER BY inv_prev.Date DESC
  LIMIT 1
) prev_ip ON true;

验证示例查询

执行以下查询:

-- 查询客户1今日发票中商品1的记录
SELECT * FROM InvoicePosView WHERE InvoicePosId = 4;

将得到预期结果:

InvoicePosId | InvoiceId | ArticleID | Quantity | Price | LastInvoicePosId
-------------|-----------|-----------|----------|-------|------------------
4            | 2         | 1         | 12.0     | 78.0  | 1

Supabase/PostgREST适配说明

  • 该视图完全兼容Supabase的PostgreSQL环境,创建后可直接通过PostgREST接口访问
  • 支持在PostgREST请求中添加筛选条件(比如?InvoiceId=eq.2来获取某发票的所有行)
  • 若需要返回更多历史行字段(如历史数量、价格),只需在子查询和视图的SELECT列表中添加对应字段即可

内容的提问来源于stack exchange,提问作者Robert P

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 19:07:08