如何按日期限制完全加入
How to limit a full join by date
我们的数据库在 SQL Server 2014 上。我遇到了与 完全相同的问题,很高兴找到答案。所以我设置了我的查询:
select distinct
coalesce (a.year, b.year+1) [Year]
, coalesce(a.Month, b.Month) [Month]
, coalesce(a.account, b.account) [Account]
, case when a.sales > 0
then a.sales
else 0 end [Sales MTD]
, case when b.sales > 0
then b.sales
else 0 end [Sales Previous Year]
, (case when b.sales!= 0
then cast((case when a.sales > 0
then a.sales
else 0 end-b.sales)/b.sales*100 as decimal(10,1))
else 0 end) [% Difference]
, sum(a.sales) over (Partition by a.account, a.year order by a.month) [Account Sales YTD]
from yourtable a
full join yourtable b
on a.account = b.account
and a.month = b.month
and a.year = b.year+1
输出为我提供了 2022 年尚未发生的几个月的结果(2023 年也开始)。 https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=9a2c29f1af08f525a1acee16b0efa2fd
我尝试将 and b.[year]+1<=year(getdate())
添加到我的连接过滤器中,但这似乎根本不会影响输出。我还尝试写了一个 where 子句,结果是一个让我头晕目眩的案例。
如何防止未来日期出现在最终结果中?
奖励问题:我能否让我的 YTD 计算接受 0 作为因销售历史记录而添加的任何行的值?
如果我没理解错的话,你需要一个左外连接,因为你关心的是一个 table 但不是两个都有记录。
在执行完全连接之前缩小相关行的列表范围。
with A as (
select *
from tableA
where ...
), B as (
select *
from tableB
where ...
)
select * from A full outer join B on ...
您也可以内联执行此操作:
select *
from
(select * from tableA where ...) as A
full outer join
(select * from tableB where ...) as B
编辑: 如果您“pre-filter”相关日期内的数据,您以后不需要进行笨拙的联合检查:
with A as (
select year, month, account, sales
from yourtable
-- if there's no future data then this whole cte may be unnecessary
where year < year(getdate())
or year = year(getdate()) and month <= month(getdate())
), B as (
select year + 1 as year, month, account, sales
from yourtable
where year < year(getdate()) - 1
or year = year(getdate()) - 1 and month <= month(getdate())
)
select
coalesce(a.year, b.year) [Year]
, coalesce(a.Month, b.Month) [Month]
, coalesce(a.account, b.account) [Account]
, sum(a.sales) over (Partition by a.account, a.year order by a.month) [Account Sales YTD]
from A full outer join B
on a.account = b.account
and a.month = b.month
and a.year = b.year
order by 1, 2
https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=26c30b190d475d8679f2253a3c428f1f
添加 WHERE
子句
...
where datefromparts(coalesce(a.year, b.year+1), coalesce(a.Month, b.Month), 1) <= cast(getdate() as date)
我们的数据库在 SQL Server 2014 上。我遇到了与
select distinct
coalesce (a.year, b.year+1) [Year]
, coalesce(a.Month, b.Month) [Month]
, coalesce(a.account, b.account) [Account]
, case when a.sales > 0
then a.sales
else 0 end [Sales MTD]
, case when b.sales > 0
then b.sales
else 0 end [Sales Previous Year]
, (case when b.sales!= 0
then cast((case when a.sales > 0
then a.sales
else 0 end-b.sales)/b.sales*100 as decimal(10,1))
else 0 end) [% Difference]
, sum(a.sales) over (Partition by a.account, a.year order by a.month) [Account Sales YTD]
from yourtable a
full join yourtable b
on a.account = b.account
and a.month = b.month
and a.year = b.year+1
输出为我提供了 2022 年尚未发生的几个月的结果(2023 年也开始)。 https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=9a2c29f1af08f525a1acee16b0efa2fd
我尝试将 and b.[year]+1<=year(getdate())
添加到我的连接过滤器中,但这似乎根本不会影响输出。我还尝试写了一个 where 子句,结果是一个让我头晕目眩的案例。
如何防止未来日期出现在最终结果中? 奖励问题:我能否让我的 YTD 计算接受 0 作为因销售历史记录而添加的任何行的值?
如果我没理解错的话,你需要一个左外连接,因为你关心的是一个 table 但不是两个都有记录。
在执行完全连接之前缩小相关行的列表范围。
with A as (
select *
from tableA
where ...
), B as (
select *
from tableB
where ...
)
select * from A full outer join B on ...
您也可以内联执行此操作:
select *
from
(select * from tableA where ...) as A
full outer join
(select * from tableB where ...) as B
编辑: 如果您“pre-filter”相关日期内的数据,您以后不需要进行笨拙的联合检查:
with A as (
select year, month, account, sales
from yourtable
-- if there's no future data then this whole cte may be unnecessary
where year < year(getdate())
or year = year(getdate()) and month <= month(getdate())
), B as (
select year + 1 as year, month, account, sales
from yourtable
where year < year(getdate()) - 1
or year = year(getdate()) - 1 and month <= month(getdate())
)
select
coalesce(a.year, b.year) [Year]
, coalesce(a.Month, b.Month) [Month]
, coalesce(a.account, b.account) [Account]
, sum(a.sales) over (Partition by a.account, a.year order by a.month) [Account Sales YTD]
from A full outer join B
on a.account = b.account
and a.month = b.month
and a.year = b.year
order by 1, 2
https://dbfiddle.uk/?rdbms=sqlserver_2014&fiddle=26c30b190d475d8679f2253a3c428f1f
添加 WHERE
子句
...
where datefromparts(coalesce(a.year, b.year+1), coalesce(a.Month, b.Month), 1) <= cast(getdate() as date)