在查询中有条件地过滤行以进一步过滤 postgres 中的查询结果

Filtering rows conditionally within a query to further filter the query result in postgres

我主要使用 NoSql 数据库,但很长一段时间后我正在尝试 SQL。我有一张 table 命名发票。

id invoice_type valid_until
01 quote 2023-03-10
02 quote 2021-03-10
03 reservation 2022-03-11

我正在尝试根据名为 type

的查询参数过滤行
  1. 如果type = reservation,Return所有行invoice_type = reservation
  2. 如果type = quote,Return所有行invoice_type = quote AND valid_until > now()
  3. 如果 type = undefined || invalid,两种类型的 Return 行,但对于具有 invoice_type = quote 的行,仍会根据 valid_until 字段过滤掉它们。

我正在为第 3 条规则而苦苦挣扎,我的想法是获取所有行,然后仅在具有 type = quote

的行上应用 valid_until 的过滤器

预期输出

GET api/invoices?type=quote
  { id: 01, invoice_type: 'quote', valid_until: '2023-03-10' }

GET api/invoices?type=reservation
  { id: 03, invoice_type: 'reservation', valid_until: '2022-03-11' }

GET api/invoices
  [
    { id: 01, invoice_type: 'quote', valid_until: '2023-03-10' },
    { id: 03, invoice_type: 'reservation', valid_until: '2022-03-11' }
  ]

目前的解决方案是

const invoices = await knex('invoices').where((builder) => {
  switch (type) {
    case 'quote':
      builder.where({ type }).where('valid_until', '>', 'now()');
      break;
    case 'reservation':
      builder.where({ type });
      break;
    default:
      console.log(type);
      builder
        .where({ type: 'quote' })
        .where('valid_until', '>', 'now()')
        .orWhere({ type: 'reservation' });
      break;
  }
});

它正在工作,但我希望完全通过 SQL 来实现它。

参数化查询中的where 子句可以完成这一切。这里是。 :type是参数。

select * from invoices
where
    (:type = 'reservation' AND invoice_type = 'reservation')
 OR (:type = 'quote' AND invoice_type = 'quote' AND valid_until > now())
 OR (:type in ('undefined', 'invalid') AND case
       when invoice_type = 'quote' then valid_until > now() 
       else true 
      end
    );