Sql server TSQL:全年/每月的连续期间
我试图找到2018年期间每个月至少有一天会员资格的所有客户 我提出了一个解决方案,在每个月初/月中/月末检查他们的会员资格,如下面的代码片段所示,但试图找到更智能的解决方案 我知道我可以使用365天的理货表来检查这一点,但可能有更优雅的解决方案?我对SQL有点陌生,我想我在分组方面遗漏了一些东西 在下面显示的代码片段中,两个Cust都至少有一天的成员资格 期望输出: 代码: 试试这个答案 首先创建一个函数,返回给定日期之间的所有月份和年份 功能: 下面是针对您的需求的T-SQL查询Sql server TSQL:全年/每月的连续期间,sql-server,tsql,Sql Server,Tsql,我试图找到2018年期间每个月至少有一天会员资格的所有客户 我提出了一个解决方案,在每个月初/月中/月末检查他们的会员资格,如下面的代码片段所示,但试图找到更智能的解决方案 我知道我可以使用365天的理货表来检查这一点,但可能有更优雅的解决方案?我对SQL有点陌生,我想我在分组方面遗漏了一些东西 在下面显示的代码片段中,两个Cust都至少有一天的成员资格 期望输出: 代码: 试试这个答案 首先创建一个函数,返回给定日期之间的所有月份和年份 功能: 下面是针对您的需求的T-SQL查询 SELECT
SELECT CustID
,COUNT(DISTINCT [Month]) NoOfMonths
FROM(
SELECT *
FROM #t t
CROSS APPLY dbo.Fn_GetMonthYear(StartDD,EndDD)
)D
WHERE [Year] = 2018
GROUP BY CustID
HAVING COUNT(DISTINCT [Month])=12
结果:
查找每个月至少有一天会员资格的所有客户
2018年的月份
我认为这意味着每个客户ID必须在“2018-01-01”和“2018-12-31”之间提供数据
未在所有样本数据中测试此脚本。
但逻辑是明确的,因此可以相应地加以纠正
因此,请说明哪些示例数据无效。给出您的DDL和一些示例数据。这是带有tally的版本:选择不同的custID、datepartmonth、dd-gaps.*、t.dd from gaps join选择前365个cast dateaddday,通过选择1-1在订单上的行数,“2018年1月1日”作为主数据日。StartDD和ENDDDD之间t.dd上的spt_值请尝试我的答案。希望它能帮助你。谢谢你!!!您的Fn_GetMonthYear是特定于用户的,看起来像理货台,对吗?你能告诉我你的fn_的输出是什么,或者把它调整到我以前粘贴的通用计数吗。德克萨斯州again@Mich28,是的,它就像理货表或数字表。@Mich28,这个答案有用吗?谢谢你和所有人
with data as
(
select *
from (values (1, 1, '2017-12-11', '2018-01-16'), (1, 22, '2018-01-28', '2018-03-9' ), (1, 333, '2018-03-1', '2018-12-31') , -- island
(22, 1, '2017-12-31', '2018-01-11'), (22, 2, '2017-2-11', '2019-12-31')) as t (CustID, ContractID, StartDD, EndDD) ---
)
select
isdate(startDD), isdate(EndDD)
from
data
), gaps as
(
select
*,
datediff(day, lag(EndDD, 1, StartDD) over (partition by CustID order by StartDD), StartDD) as BreakDD -- negative is island
from
data
)
select
*,
datepart(month,StartDD) mmS , datepart(month,EndDD) mmE
from
gaps
-- and was active any 1+ day during each of the 12 months in 2018 ????
where
1 = 1
/* and (cast('1/1/2018' as date) between StartDD and EndDD
or cast('1/15/2018' as date) between StartDD and EndDD
or cast('1/31/2018' as date) between StartDD and EndDD)
---- etc.. for each month
and ( cast('12/1/2018' as date) between StartDD and EndDD
or cast('12/15/2018' as date) between StartDD and EndDD
or cast('12/31/2018' as date) between StartDD and EndDD
)
*/
--select CustID, max(BreakDD) Max_Days
--from gaps
--group by CustID
--SELECT * FROM dbo.Fn_GetMonthYear('2017-12-11','2018-01-16')
ALTER FUNCTION dbo.Fn_GetMonthYear(@StartDate DATETIME,@EndDate DATETIME)
RETURNS TABLE
AS
RETURN(
SELECT DATEPART(MONTH, DATEADD(MONTH, x.number, @StartDate)) AS [Month]
,DATEPART(YEAR, DATEADD(MONTH, x.number, @StartDate)) AS [Year]
FROM master.dbo.spt_values x
WHERE x.type = 'P'
AND x.number <= DATEDIFF(MONTH, @StartDate, @EndDate)
)
CREATE TABLE #t(CustID INT, ContractID INT, StartDD date, EndDD date)
INSERT INTO #t values (1, 1, '2017-12-11', '2018-01-16'), (1, 22, '2018-01-28', '2018-03-9' ), (1, 333, '2018-03-1', '2018-12-31') , -- island
(22, 1, '2017-12-31', '2018-01-11'), (22, 2, '2017-2-11', '2019-12-31')
SELECT CustID
,COUNT(DISTINCT [Month]) NoOfMonths
FROM(
SELECT *
FROM #t t
CROSS APPLY dbo.Fn_GetMonthYear(StartDD,EndDD)
)D
WHERE [Year] = 2018
GROUP BY CustID
HAVING COUNT(DISTINCT [Month])=12
CustID NoOfMonths
1 12
22 12
CREATE TABLE #t(CustID INT, ContractID INT, StartDD date, EndDD date)
INSERT INTO #t values (1, 1, '2017-12-11', '2018-01-16'), (1, 22, '2018-01-28', '2018-03-9' ), (1, 333, '2018-03-1', '2018-12-31') , -- island
(22, 1, '2017-12-31', '2018-01-11'), (22, 2, '2017-2-11', '2019-12-31')
declare @From Datetime='2018-01-01'
declare @To datetime='2018-12-31'
;with CTE as
(
select CustID,min(StartDD)StartDD
,max(EndDD)EndDD
from #t
group by CustID
)
select CustID,StartDD
,EndDD
from CTE
where StartDD<=@From and EndDD>=@To