SQL 交易 table 中*日期范围*不匹配

SQL where no match *for date range* in transaction table

我不太明白这一点:我想要 master table 中所有那些在给定的事务 table、 中没有匹配事务行的行日期范围。例子: 大师 table 米:

id Name
1  John
2  David
3  Simon 
4  Jessica
5  Becky

交易tablet

id parent date       action
1  1      2015-08-28 IN
2  1      2015-09-03 IN
3  2      2015-08-17 IN
4  2      2015-10-01 IN
5  4      2015-09-05 IN

我想要 m 中所有在 9 月没有任何交易的条目:所以我应该得到 m.id 2,3,5

1 does not match: events in september
2 matches: events but none in  september
3 matches: no events at all
4 does not match: events in september
5 matches: No events at all

我可以通过左连接获得 t 中没有任何内容的条件,以及通过连接获得具有日期但不在范围内的条件的条件,但看不到如何同时获得这两个条件。我可能只是度过了无聊的一天。

select 所有主节点,加入按父级分组的事务(这导致每个主条目有 0..1 行)。

如果没有交易记录,t.parent 将为空,这意味着该主条目没有交易。

如果有交易条目,您将在 t.a 中找到计数,如果其中一些在 9 月,您将在 t.m9

中找到它们

如果你想要所有没有任何交易的主人,你会过滤t.parent is null

如果您希望所有 master 在 9 月都没有交易,您将过滤 t.parent is null or t.m9=0

select m.id, m.name, 
     , t.a, t.m9 
from master_table m
left join ( select a  = count(*)
                 , m9 = count(case when datepart(Month, t.date) = 9 then 1 end)
                 , t.parent 
            from transaction_table t 
            group by t.parent
          ) t on t.parent = m.id
where t.parent is null or t.m9=0

通常,当我们尝试直接跳转到最终查询时,结果可能会复杂得多——如果它能工作的话。通常,直接对有问题的表执行连接并查看结果并没有什么坏处。如果不出意外,您验证连接是否正确:

with
Master( ID, Name )as(
    select  1, 'John' from dual union all
    select  2, 'David' from dual union all
    select  3, 'Simon' from dual union all
    select  4, 'Jessica' from dual union all
    select  5, 'Becky' from dual
),
Trans( MasterID, EffDate, Action )as(
    select  1, date '2015-08-28', 'IN' from dual union all
    select  1, date '2015-09-03', 'IN' from dual union all
    select  2, date '2015-08-17', 'IN' from dual union all
    select  2, date '2015-10-01', 'IN' from dual union all
    select  4, date '2015-09-05', 'IN' from dual
)
select  *
from    Master  m
join    Trans   t
    on  t.MasterID  = m.ID;

(请原谅我重命名了您的一些字段。)我现在正好有 Oracle,您可以使用任何东西。通过从 CTE 代码中删除 'from dual',此代码可能适用于任何非 Oracle 系统。

现在让我们扩展连接条件,但这样做是为了生成我们不想看到的数据。

join    Trans   t
    on  t.MasterID  = m.ID
    and t.EffDate >= date '2015-09-01'
    and t.EffDate < date '2015-10-01';

我已经对日期值进行了硬编码,但这是用于获取 "during the month of..." 范围的最佳格式。每个值都是从当月第一天的第一个报价单到下个月第一天之前的最后一个报价单选择的。当然,您需要将这些值存储在变量中或即时生成它们。

现在我们只看到 9 月份期间发生的两笔交易。显而易见的下一步是执行外部联接,以便我们获得所有其他不匹配的主记录。

left join Trans   t

现在我们拥有所有想要的记录,加上我们不想要的两个。由于它们是唯一符合日期限制的,我们添加过滤条件以删除它们。这是最终查询:

select  m.*
from    Master  m
left join Trans   t
    on  t.MasterID  = m.ID
    and t.EffDate >= date '2015-09-01'
    and t.EffDate < date '2015-10-01'
where   t.MasterID is null;

真的很简单。完成几次后,您将能够跳转到完成的查询,而无需中间步骤。不过,执行中间步骤并查看过程中的输出并没有什么坏处。如果可以更轻松地修复逻辑中的任何缺陷,将会更早地发现它。