我有一个包含员工信息的表EMPLOYEE,如下所述:
ID NAME DOB
1 ABC 1974-01-01
2 BDS 1984-12-31
3 QWE 1959-05-27
and so on
我想列出DOB在给定范围内的所有员工。
select * from EMPLOYEE where DOB BETWEEN '1970-01-01' AND '1980-02-27'
我有一个过滤条件'包括年度比较',当选择'否'时,员工DOB日和DOB月 只应考虑进行比较。 而不是年份。
例如:如果我输入日期范围为'1970-01-01'和'1980-02-27'并且过滤器被选为'否'则它应该只搜索那些员工 其DOB大于等于JAN-01且小于等于FEB-27。
选择'是'时,它只是上述查询中提到的日期范围。
这是我到目前为止所尝试的内容:
select * from EMPLOYEE where DOB BETWEEN '1970-01-01' AND '1980-02-27'
AND MONTH(DOB) >= CASE WHEN 'NO'='NO' THEN MONTH('1970-01-01')
ELSE MONTH(DOB) END
AND MONTH(DOB) <= CASE WHEN 'NO'='NO' THEN MONTH('1980-02-27')
ELSE MONTH(DOB) END
AND DAY(DOB) >= CASE WHEN 'NO'='NO' THEN DAY('1970-01-01')
ELSE DAY(DOB) END
AND DAY(DOB) <= CASE WHEN 'NO'='NO' THEN DAY('1980-02-27')
ELSE DAY(DOB) END
当我通过FROM日期的月份数小于TO日期月份的日期范围时,它会起作用。
例如: 当我将日期范围作为'1970-12-01'传递给'1980-01-31'时,它不起作用。 它应列出DOB在DEC和JAN月份的员工。
请帮助。
答案 0 :(得分:2)
DECLARE @includeYear bit = 0, -- if 0 - we don't include year, 1 - include
@dateFrom date ='1970-12-01',
@dateTo date ='1980-05-30'
IF @includeYear = 1
BEGIN
SELECT e.*
FROM EMPLOYEE e
INNER JOIN (SELECT @dateFrom as dF, @dateTo as dT) d
ON e.DOB BETWEEN dF AND dT
END
ELSE
BEGIN
SELECT e.*
FROM EMPLOYEE e
INNER JOIN (SELECT @dateFrom as dF, @dateTo as dT) d
ON e.DOB BETWEEN
(CASE WHEN MONTH(dF) > MONTH(dT)
THEN DATEADD(year,YEAR(e.DOB)-YEAR(d.dF)-1,dF)
ELSE DATEADD(year,YEAR(e.DOB)-YEAR(d.dF),dF) END)
AND DATEADD(year,YEAR(e.DOB)-YEAR(d.dT),dT)
OR e.DOB BETWEEN DATEADD(year,YEAR(e.DOB)-YEAR(d.dF),dF) AND
(CASE WHEN MONTH(dF) > MONTH(dT)
THEN DATEADD(year,YEAR(e.DOB)-YEAR(d.dT)+1,dT)
ELSE DATEADD(year,YEAR(e.DOB)-YEAR(d.dT),dT) END)
END
对于
dateFrom dateTo
1970-12-01 1980-01-30
输出:
ID NAME DOB
1 ABC 1974-01-01
2 BDS 1984-12-31
对于
dateFrom dateTo
1970-05-01 1980-06-30
输出:
ID NAME DOB
3 QWE 1959-05-27
有关
dateFrom dateTo
1970-05-01 1980-05-30
输出:
ID NAME DOB
3 QWE 1959-05-27
等
答案 1 :(得分:2)
样本数据;
DECLARE @Date_From date; SET @Date_From = '1970-12-01'
DECLARE @Date_To date; SET @Date_To = '1974-01-31'
DECLARE @IncludeYear bit; SET @IncludeYear = 0
CREATE TABLE #Employee (ID int, Name varchar(10), DOB date)
INSERT INTO #Employee (ID, Name, DOB)
VALUES
(1,'ABC','1974-01-01')
,(2,'BDS','1984-12-31')
,(3,'QWE','1959-05-27')
这是我所提出的问题。试图弥补每一种可能性。
SELECT
e.ID
,e.Name
,e.DOB
FROM #Employee e
WHERE
(
@IncludeYear = 1
AND
DOB BETWEEN @Date_From AND @Date_To
)
OR
(
@IncludeYear = 0
AND
(
(
DATEPART(DAYOFYEAR, @Date_From) = DATEPART(DAYOFYEAR, @Date_To)
AND
DATEPART(DAYOFYEAR, DOB) = DATEPART(DAYOFYEAR, @Date_To)
)
OR
(
DATEPART(DAYOFYEAR, @Date_From) < DATEPART(DAYOFYEAR, @Date_To)
AND
DATEPART(DAYOFYEAR, DOB) BETWEEN DATEPART(DAYOFYEAR, @Date_From) AND DATEPART(DAYOFYEAR, @Date_To)
)
OR
(
DATEPART(DAYOFYEAR, @Date_From) > DATEPART(DAYOFYEAR, @Date_To)
AND
(
DATEPART(DAYOFYEAR, DOB) > DATEPART(DAYOFYEAR, @Date_From)
OR
DATEPART(DAYOFYEAR, DOB) < DATEPART(DAYOFYEAR, @Date_To)
)
)
)
)
这个的结果就是这样;
ID Name DOB
1 ABC 1974-01-01
2 BDS 1984-12-31
答案 2 :(得分:0)
尝试功能{{1}}
如果第一个日期的年份小于第二个日期的日期,那么DOB的年份应该在指定的年份之间。
否则,DOB的年度应小于第二个日期的日期或大于第一个日期的日期。
我希望自己表达得很好。
答案 3 :(得分:0)
我没有逐案处理,拆解和重新组装部分日期,而是试图让生活更轻松:
declare @t table (ID int not null, Name varchar(17) not null, DOB date not null)
insert into @t(ID,NAME,DOB) values
(1,'ABC','19740101'),
(2,'BDS','19841231'),
(3,'QWE','19590527')
declare @Start date
declare @End date
declare @IncludeYear bit
select @Start='19701201',@End='19800131',@IncludeYear=0
;With Normalized as (
select
ID,
Name,
CASE WHEN @IncludeYear=1 THEN DOB
ELSE DATEADD(year,DATEDIFF(year,DOB,'20000101'),DOB)
END as DOB,
CASE WHEN @IncludeYear=1 THEN @Start
ELSE DATEADD(year,DATEDIFF(year,@Start,'20000101'),@Start)
END as StartRange,
CASE WHEN @IncludeYear=1 THEN @End
ELSE DATEADD(year,DATEDIFF(year,@End,'20000101'),@End)
END as EndRange
from
@t
)
select * from Normalized
where
DOB between StartRange and EndRange or
(
@IncludeYear=0 and StartRange>EndRange and
(
DOB < EndRange or DOB > StartRange
)
)
我们创建Normalized
CTE,如果@IncludeYear
为1,则不执行任何操作,如果为零,则会重置所有日期,以便它们在2000年(任意选择)发生。
然后,我们根据CTE进行简单的查询。它不能正确匹配的一种情况是,当您在年终过渡期间确定了您的范围并且我们不关心多年 - 我们可以专门检查并在最后期限内满足WHERE
条款。
结果:
ID Name DOB StartRange EndRange
----------- ----------------- ---------- ---------- ----------
1 ABC 2000-01-01 2000-12-01 2000-01-31
2 BDS 2000-12-31 2000-12-01 2000-01-31
@Start='19700101',@End='19800227',@IncludeYear=1
的结果:
ID Name DOB StartRange EndRange
----------- ----------------- ---------- ---------- ----------
1 ABC 1974-01-01 1970-01-01 1980-02-27
答案 4 :(得分:0)
试试这个。
declare @flag varchar(3) ='NO';
declare @sd date ='1980-02-27';
declare @ed date ='1970-01-01';
select tt.*
from (select sd = month(@sd)*100 + day(@sd),
ed = month(@ed)*100 + day(@ed)
) prm
cross join
-- test data, place real table here
(
values
(1,'ABC', cast('1974-01-05' as date)),
(2,'BDS','1984-12-31'),
(3,'QWE','1959-05-27')
) tt(ID,NAME, DOB)
cross apply (select md = month(DOB)*100 + day(DOB)) tx
where @flag ='YES' and DOB between @sd and @ed
or @flag ='NO' and (prm.sd<=prm.ed and tx.md between prm.sd and prm.ed
or prm.sd>prm.ed and (tx.md <= prm.ed or tx.md >= prm.sd));
答案 5 :(得分:0)
这是另一种解决方案
var client = new kafka.Client(ZOO_KEEPER_URL, PORTAL_CLIENT_ID);
var topics = [
{ "topic" : MY_TOPIC_NAME,
partition: 0
},
{ "topic" : MY_TOPIC_NAME,
partition: 1 }
];
var options = {
autoCommit: false,
groupId: GROUP_ID,
fromOffset : false
};
var consumer = new Consumer(client, topics, options);
consumer.on('message', function (message) {
console.log("New Message; offset: "+ message.offset + " Partition: "+message.partition);
});
正如您所看到的,如果您不想包含年份,我们只是将查询的年份作为常量。这个查询似乎有点慢,但是如果你在表中添加另一个计算列,在那里用一年的常量保存日期,那么你只需要在那个特定列上放置标准。
答案 6 :(得分:0)
您想要的是根据过程的答案运行两个不同的查询。由于这是一个可能会运行很多的过程,因此将答案存储到PROC中的变量中并从那里运行任何调整代码。这不仅可以通过预先清除错误来使代码更加健壮,而且SQL Server更有可能猜测要与索引一起使用的变量。
以下PROC将有效。随意使用部分或全部:
CREATE TABLE #table_E (ID INT, Name VARCHAR(3), DOB DATE)
INSERT INTO #table_E (ID , Name, DOB)
VALUES (1, 'ABC', '1997-01-02' )
, (2, 'BDS', '1984-12-31' )
, (3, 'QWE', '1993-03-22' )
GO
CREATE PROC USP_EmpCompare (@Date_1 DATE, @Date_2 DATE, @Compare_Year VARCHAR(3))
AS
BEGIN
DECLARE @MONTH_1 INT
, @Month_2 INT
, @Day_1 INT
, @Day_2 INT
, @Date1 DATE
, @Date2 DATE
SET @Date1 = CASE WHEN @Date_1 > @Date_2 THEN @Date_2 ELSE @Date_1 END
SET @Date2 = CASE WHEN @Date_1 > @Date_2 THEN @Date_1 ELSE @Date_2 END
SET @Month_1 = CASE WHEN DATEPART(MM, @Date2) > DATEPART(MM, @Date1) THEN DATEPART(MM, @Date1) ELSE DATEPART(MM, @Date2) END
SET @Month_2 = CASE WHEN DATEPART(MM, @Date1) > DATEPART(MM, @Date2) THEN DATEPART(MM, @Date1) ELSE DATEPART(MM, @Date2) END
SET @Day_1 = CASE WHEN DATEPART(DD, @Date2) > DATEPART(DD, @Date1) THEN DATEPART(DD, @Date1) ELSE DATEPART(DD, @Date2) END
SET @Day_2 = CASE WHEN DATEPART(DD, @Date1) > DATEPART(DD, @Date2) THEN DATEPART(DD, @Date1) ELSE DATEPART(DD, @Date2) END
-- SELECT @Date1, @Date2
IF @Compare_Year = 'no'
BEGIN
;WITH C AS (SELECT ID
, Name
, DATEPART(DD, DOB) AS Day
, DATEPART(MM, DOB) AS Month
FROM #table_E)
SELECT ID, Name, @Date1, @Date2
FROM C
WHERE C.Month >= @MONTH_1
AND C.Month <= @Month_2
AND C.Day >= @Day_1
AND C.DAy <= @Day_2
END
IF @Compare_Year = 'yes'
BEGIN
SELECT ID, Name, DOB
FROM #table_E
WHERE DOB <= @Date2
AND DOB >= @Date1
END
ELSE
PRINT WHAT! FOLLOW THE RULES YOU FOOL!!!
END
JK。关于傻瓜的最后一部分可能不包括在你的最终草案中。 ;)
答案 7 :(得分:0)
我会让它变得非常简单,而不是那么复杂。
SELECT * FROM EMPLOYEE WHERE DOB >= '1970-01-01' AND DOB <= '1980-02-27'
这会过滤这两个日期之间的所有日期