我是这里的新手,非常感谢任何帮助。我需要创建一个老化设置为> 3个月,> 6个月,> 9个月的报告。
报告应该只有3列(3个月,> 6个月,> 9个月)。在表/数据库中假设我们只有两个字段。一个是WELL_ID,用于标识井的名称和RECORD_DATE(mm / dd / yyyy),用于标识上次测试WELL的时间。我们希望报告能够在3个月或> 6个月或> 9个月内进行测试。
我相信一个案例陈述可以放在一起来创建这个结果集,但我在如何做到这一点上画了一个空白。如果有人可以使用Case Statement发布解决方案,那将非常感激。如果他们甚至可以花时间向我解释解决方案,那么帮助我理解会更好。
此致
SQL新手
答案 0 :(得分:1)
如果你想获得3列> 3个月,> 6个月,> 9个月,每个人使用well_id返回,我可以告诉你如何在SQL中执行此操作。但是,最好在报表级别执行此操作,并且仅分别从SQL检索每个列。这是微不足道的,其他人已经给你一些例子。
让我们开始吧。首先,SQL中的datediff不是人们期望它的行为方式。您可以在this article中阅读有关它的所有内容。让我们从那里借用一个函数:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[fnMonthsApart]') AND type in (N'FN'))
DROP FUNCTION dbo.fnMonthsApart
GO
CREATE FUNCTION dbo.fnMonthsApart
(
@FromDate DATETIME,
@ToDate DATETIME
)
RETURNS INT
AS
BEGIN
RETURN CASE
WHEN @FromDate > @ToDate THEN NULL
WHEN DATEPART(day, @FromDate) > DATEPART(day, @ToDate) THEN DATEDIFF(month, @FromDate, @ToDate) - 1
ELSE DATEDIFF(month, @FromDate, @ToDate)
END
END
GO
出色!现在让我们定义我们的表格:
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[Well]') AND type in (N'U'))
DROP TABLE [dbo].[Well]
GO
CREATE TABLE [dbo].[Well](
[WELL_ID] [int] IDENTITY(1,1) NOT NULL,
[RECORD_DATE] [datetime] NOT NULL,
CONSTRAINT [PK_Well] PRIMARY KEY CLUSTERED
(
[WELL_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
以及一些示例数据:
declare @date datetime = dateadd(d,-1,getdate())
INSERT INTO [dbo].[Well]([RECORD_DATE]) VALUES (dateadd(m,-12,@date))
INSERT INTO [dbo].[Well]([RECORD_DATE]) VALUES (dateadd(m,-9,@date))
INSERT INTO [dbo].[Well]([RECORD_DATE]) VALUES (dateadd(m,-9,@date))
INSERT INTO [dbo].[Well]([RECORD_DATE]) VALUES (dateadd(m,-9,@date))
INSERT INTO [dbo].[Well]([RECORD_DATE]) VALUES (dateadd(m,-9,@date))
INSERT INTO [dbo].[Well]([RECORD_DATE]) VALUES (dateadd(m,-9,@date))
INSERT INTO [dbo].[Well]([RECORD_DATE]) VALUES (dateadd(m,-6,@date))
INSERT INTO [dbo].[Well]([RECORD_DATE]) VALUES (dateadd(m,-6,@date))
INSERT INTO [dbo].[Well]([RECORD_DATE]) VALUES (dateadd(m,-6,@date))
INSERT INTO [dbo].[Well]([RECORD_DATE]) VALUES (dateadd(m,-6,@date))
INSERT INTO [dbo].[Well]([RECORD_DATE]) VALUES (dateadd(m,-3,@date))
INSERT INTO [dbo].[Well]([RECORD_DATE]) VALUES (dateadd(m,-3,@date))
INSERT INTO [dbo].[Well]([RECORD_DATE]) VALUES (dateadd(m,-3,@date))
INSERT INTO [dbo].[Well]([RECORD_DATE]) VALUES (@date)
GO
到目前为止,非常好。
现在,技巧是分别检索三列,然后将它们连接在一个记录集中。以下是如何做到这一点:
declare @date datetime = getdate();
with AgeGrouping as
(select
WELL_ID,
dbo.fnMonthsApart(record_date,@date) MonthsAgo,
case
when dbo.fnMonthsApart(record_date,@date) >= 9 then 1
when dbo.fnMonthsApart(record_date,@date) >= 6 then 2
when dbo.fnMonthsApart(record_date,@date) >= 3 then 3
else 4
end AgeGroup,
ROW_NUMBER() OVER (partition by
case
when dbo.fnMonthsApart(record_date,@date) >= 9 then 1
when dbo.fnMonthsApart(record_date,@date) >= 6 then 2
when dbo.fnMonthsApart(record_date,@date) >= 3 then 3
else 4
end
order by WELL_ID) RowNumber
from well
),
MoreThan9Group as
(select * from AgeGrouping where AgeGroup = 1
),
MoreThan6Group as
(select * from AgeGrouping where AgeGroup = 2
),
MoreThan3Group as
(select * from AgeGrouping where AgeGroup = 3
)
select g1.WELL_ID MoreThan9,g2.WELL_ID MoreThan6,g3.WELL_ID MoreThan3
from MoreThan9Group g1 full join MoreThan6Group g2 on (g1.RowNumber = g2.RowNumber)
full join MoreThan3Group g3 on ((g1.RowNumber = g3.RowNumber) or (g2.RowNumber = g3.RowNumber))
请注意,我在此SQL中有>=
而不是>
。这是因为1月1日到4月2日之间的差异超过3个月,但3是我们比较它们时返回的数字。因此,3的结果符合您的要求,因此我们将>
更改为>=
以包含它。
就是这样。
答案 1 :(得分:0)
我不确定这是否是您正在寻找的。我还没试过。
CASE语句检查DATEDIFF函数返回的值。取决于该值是> 9或> 6或> 3或< = 3,确定test_Status。
SELECT well_ID,
record_Date,
CASE
WHEN DATEDIFF(month, record_Date, GETDATE()) >= 9
THEN 'Not Tested In More Than 9 Months'
WHEN DATEDIFF(month, record_Date, GETDATE()) >= 6
THEN 'Not Tested In More Than 6 Months'
WHEN DATEDIFF(month, record_Date, GETDATE()) >= 3
THEN 'Not Tested In More Than 3 Months'
ELSE 'Tested Within Last 3 Months'
END AS test_Status
FROM WellTable;
答案 2 :(得分:0)
您可以根据以下逻辑首先计算RECORD_DATE和今天之间的月数:
a)如果RECORD_DATE的日期部分>今天的部分日期+ 1,然后是#个月=使用DATEDIFF获得的月数#1
b)如果RECORD_DATE的日期部分不是>今天的部分日期+ 1,然后是#个月=使用DATEDIFF获得的月份数
然后,根据月数,确定状态。
WITH month_interval AS
(
SELECT
WELL_ID,
CASE
WHEN DATEPART(DAY, RECORD_DATE) > DATEPART(DAY, GETDATE())+1 THEN DATEDIFF(MONTH, RECORD_DATE, GETDATE())-1
ELSE DATEDIFF(MONTH, RECORD_DATE, GETDATE())
END num_months
FROM WellTable
)
SELECT
wt.WELL_ID,
wt.RECORD_DATE,
CASE
WHEN mi.num_months >= 9 THEN 'Not Tested In More Than 9 Months'
WHEN mi.num_months >= 6 THEN 'Not Tested In More Than 6 Months'
WHEN mi.num_months >= 3 THEN 'Not Tested In More Than 3 Months'
ELSE 'Tested Within Last 3 Months'
END AS TEST_STATUS
FROM WellTable wt
INNER JOIN month_interval mi
ON wt.WELL_ID = mi.WELL_ID;