【问题标题】:SQL WITH statementSQL WITH 语句
【发布时间】:2021-05-12 20:46:25
【问题描述】:

我有以下问题。如何将 invoice_dt 设置在 2021 年 1 月 1 日至 2021 年 5 月 31 日之间...输出显示所有日期范围。我将如何设置它以在日期范围内根据 pay_cte 查找重复?

with pay_cte( vendor_id,invoice_id, pay_amt,pay_cnt ) as (
select vendor_id,invoice_id, pay_amt,count(*)
from ps_voucher
where invoice_dt between '01-Jan-2021' and '31-May-2021'
group by vendor_id,invoice_id, pay_amt
having count(*)>1)
select t.vendor_id, t.voucher_id,t.INVOICE_ID,t.gross_amt, t.INVOICE_DT
from ps_voucher t
join pay_cte p on t.vendor_id=p.vendor_id and t.invoice_id = p.invoice_id
and t.gross_amt=p.pay_amt

【问题讨论】:

  • 样本数据和期望的结果在这里会有很长的路要走。
  • invoice_dt的数据类型是什么?
  • 您加入的列不是唯一标识符,因为您将它们分组。因此,当您使用它们连接回原始表时,您将获得符合连接子句的所有行。不再过滤日期列。
  • 您的样本数据在哪里? ps_voucher 中可能有匹配的行(您的加入条件)超出该范围。

标签: sql oracle common-table-expression


【解决方案1】:

您的查询返回所有日期的原因是因为您使用WITH 子句的实际选择语句没有对日期进行任何过滤。您的ps_voucher 表中的记录很可能包含INVOICE_DT 值超出您感兴趣的日期范围的记录。

有两种方法可以过滤结果;第一个是在(内部)JOIN 子句中,第二个是在查询中添加一个WHERE 子句。

选项 1:

with pay_cte( vendor_id,invoice_id, pay_amt,pay_cnt ) as (
    select 
        vendor_id,
        invoice_id, 
        pay_amt,
        count(*)
    from ps_voucher
    where 
        invoice_dt between '01-Jan-2021' and '31-May-2021'
    group by 
        vendor_id,
        invoice_id,
        pay_amt
    having 
        count(*)>1
)
select 
    t.vendor_id, 
    t.voucher_id,
    t.INVOICE_ID,
    t.gross_amt,
    t.INVOICE_DT
from ps_voucher t
join pay_cte p 
    on t.vendor_id = p.vendor_id 
    and t.invoice_id = p.invoice_id
    and t.gross_amt=p.pay_amt
    and t.INVOICE_DT between '01-Jan-2021' and '31-May-2021'

选项 2:

with pay_cte( vendor_id,invoice_id, pay_amt,pay_cnt ) as (
    select 
        vendor_id,
        invoice_id, 
        pay_amt,
        count(*)
    from ps_voucher
    where 
        invoice_dt between '01-Jan-2021' and '31-May-2021'
    group by 
        vendor_id,
        invoice_id,
        pay_amt
    having 
        count(*)>1
)
select 
    t.vendor_id, 
    t.voucher_id,
    t.INVOICE_ID,
    t.gross_amt,
    t.INVOICE_DT
from ps_voucher t
join pay_cte p 
    on t.vendor_id = p.vendor_id 
    and t.invoice_id = p.invoice_id
    and t.gross_amt=p.pay_amt
where
    t.INVOICE_DT between '01-Jan-2021' and '31-May-2021'

【讨论】:

    【解决方案2】:

    您必须将日期更改为“yyyy-mm-dd”格式

    【讨论】:

    • 01-Jan-2021 --> 2021-01-01
    • OP 似乎依赖隐式转换将其字符串日期值转换为日期数据类型;虽然这是不好的做法,但它会起作用(前提是 NLS_DATE_FORMAT 不会改变)。 db<>fiddle
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-08
    • 2011-08-07
    • 2020-10-26
    • 1970-01-01
    • 2013-01-01
    • 2020-04-01
    相关资源
    最近更新 更多