2017-01-02 2 views
0

현재 SQL Server 언어로 C#을 작업하고 있으며 쿼터 (Q1, Q2, Q3, Q4)를 선택해야하는 쿼리를 디자인하려고합니다.SQL에서 여러 날짜 범위 선택 쿼리

제 문제는 프런트 엔드의 사용자가 Q1 만 선택한 다음 분기 Q1에 대해 기간을 설정할 수 있다고 가정하고 사용자가 Q1을 선택하고 Q2를 선택한 경우에도 여전히 날짜를 설정할 수 있다고 가정합니다. Q1과 Q2의 범위는 시퀀스 날짜 범위에 속하기 때문에

그러나 사용자가 Q1 및 Q3을 선택하면 저장 프로 시저 또는 단순 선택 쿼리에서 날짜 범위 쿼리를 준비하고이를 위해 어떻게해야합니까?

나는 이것을 사용해 봤지만 사용하지는 않았다.

where CDate in(cdate between '2015-05-20' and '2015-06-01' 
    and CDate between '2016-06-03' and '2016-06-04' 

select * from MM where @innerstring 

나는 SQL 저장 프로 시저에 매개 변수로 보낸 다음 준비하려는 @innerstring /를 실행합니다. 하지만 임시 테이블을 사용하여 쿼리 데이터를 저장하고 결과를 통합하는 데 temp 테이블을 사용하고 싶지 않습니다. 나는 다른 매개 변수도 가지고 있기 때문에.

감사합니다.

+0

왜 MySQL의 태그를? – jarlh

+0

예제 데이터와 예상 결과를 추가해야합니다. 우리는 quaters 또는 날짜로 수행하고자하는 것을 완전히 이해하지 못합니다. – Deadsheep39

답변

2

in은 필요하지 않습니다. 이 작업을해야합니다 : 아론 버트 랜드는 흥미로운 blog에 설명으로 날짜와 between가 위험/midleading 될 수 있음을

where (cdate between '2015-05-20' and '2015-06-01' or 
     cdate between '2016-06-03' and '2016-06-04' 
    ) 

참고. cdate는 시간 구성 요소가 경우에도

where (cdate >= '2015-05-20' and cdate < '2015-06-02' or 
     cdate >= '2016-06-03' and cdate < '2016-06-05' 
    ) 

이 안전하게 작동 : 나는 갈 것이다.

+0

첫 번째 날짜 범위에 대한 레코드를 선택하거나 아무것도하지 않습니다. 두 날짜 범위 모두에 결과를 포함시키고 싶습니다. 즉, cdate> = '2015-05-20'에서 모든 레코드를 선택하고 <2015-06-02 '을 cdate 한 다음 cdate> ='2016- 06-03 '및 <2016-06-05'도 작성하십시오. – Saleem

+0

예. 감사합니다. 나는 지금 일했다. 하지만 SQL 쿼리에서 어떻게 준비 할 것인가? Q1부터 Q4까지를 무작위로 선택하기 때문에 상황에 따라 쿼리를 어떻게 준비 할 수 있습니까? 쿼리는 SQL 저장 프로 시저에 있어야합니다. – Saleem

+0

** 고든 리노프 **, 위의 아이디어. – Saleem

0

분기를 기준으로 기간을 선택하려면 달력 표를 사용하여이를 용이하게 할 수 있습니다. 다음 예제에서는 Creating a date dimension or calendar table in SQL Server - Aaron Bertrand의 발췌 문장을 사용합니다.

-- if regional settings are interfering with interpretation of dates/literals: 
/* 
set datefirst 7; 
set dateformat mdy; 
set language us_english; 
--*/ 
if object_id('dbo.Calendar_Example') is not null drop table dbo.Calendar_Example; 
create table dbo.Calendar_Example (
    [Date]   date  not null 
    , [Year]   smallint not null 
    , [Day]   tinyint not null 
    , [Month]  tinyint not null 
    , [Quarter]  tinyint not null 
    , [YearQuarter] char(7) not null /* yyyy-qq */ 
    , constraint pk_Calendar_Quarters primary key clustered (date) 
); 

declare @FromDate date = '20160101'; 
declare @ThruDate date = '202'; 

with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n)) 
, d as (
    select DateValue=convert(date,dateadd(day 
     , row_number() over (order by (select 1)) -1, @fromdate)) 
    from   n as deka 
     cross join n as hecto 
     cross join n as kilo  /* 2.73 years */ 
     cross join n as [10k] /* 27.3 years */ 
     --cross join n as [100k] /* 273 years */ 
     --cross join n as mega 
) 
insert into dbo.Calendar_Example 
    ([Date], [Year], [Day], [Month], [Quarter], [YearQuarter]) 
    select top (datediff(day, @FromDate, @ThruDate)+1) 
     [Date]  = DateValue 
    , [Year]  = convert(smallint,datepart(year,DateValue)) 
    , [Day]   = convert(tinyint,datepart(day,DateValue)) 
    , [Month]  = convert(tinyint,datepart(month,DateValue)) 
    , [Quarter]  = convert(tinyint,datepart(quarter,DateValue)) 
    , [YearQuarter] = convert(char(7) ,convert(char(4), datepart(year,DateValue)) 
         +'-Q'+convert(char(1), datepart(quarter,DateValue))) 
    from d 
    order by DateValue; 

일정 숫자 표 참조 :


여기에서, 당신은 선택에 포함 분기 세트를 전달하는 테이블 반환 매개 변수 (TVP)을 사용할 수 있습니다.예 :

create type dbo.DateRange_udt as table (
    FromDate date not null 
    , ThruDate date not null 
    primary key (FromDate,ThruDate) 
    ); 
go 

create procedure dbo.Select_Using_DateRange_udt (
    @DateRange dbo.DateRange_udt readonly 
) as 
begin; 
    set nocount on; 
    set xact_abort on; 
    select * 
    from MM 
     inner join @DateRange dr on mm.CDate >= dr.FromDate 
           and mm.CDate <= dr.ThruDate 
end; 
go 

테이블 반환 매개 변수 참조 :


TVPs에 대한 대안

  • how to use TVPs with Entity Framework 4.1 and CodeFirst
  • , 당신은 @innerstring 변수를 분할 수 있습니다. 및 (코멘트 약간 제거 포맷) Jeff Moden's DelimitedSplitN4k를 이용한다 '

    create procedure dbo.Select_Using_YearQuarter_Delimited (
        @DelimitedString nvarchar(256) 
    ) as 
    begin; 
        set nocount on; 
        set xact_abort on; 
        with c as (
        select ce.[Date] 
         from dbo.Calendar_Example ce 
         inner join dbo.DelimitedSplitN4k(@DelimitedString,';') as d 
          on convert(char(7),d.Item) = ce.YearQuarter 
        ) 
        select * 
        from MM 
         inner join c on mm.CDate = c.Date; 
    end; 
    go 
    

    상기 예제의 분리를 가정한다.

    create function dbo.DelimitedSplitN4K (
        @pString nvarchar(4000) 
        , @pDelimiter nchar(1) 
    ) 
    returns table with schemabinding as 
    return 
        with e1(n) as (
        select 1 union all select 1 union all select 1 union all 
        select 1 union all select 1 union all select 1 union all 
        select 1 union all select 1 union all select 1 union all select 1 
    ) 
        , e2(n) as (select 1 from e1 a, e1 b) 
        , e4(n) as (select 1 from e2 a, e2 b) 
        , cteTally(n) as (select top (isnull(datalength(@pString)/2,0)) 
         row_number() over (order by (select null)) from e4) 
        , cteStart(n1) as (select 1 union all 
         select t.n+1 from cteTally t where substring(@pString,t.n,1) = @pDelimiter) 
        , cteLen(n1,l1) as(select s.n1 
        , isnull(nullif(charindex(@pDelimiter,@pString,s.n1),0)-s.n1,4000) 
        from cteStart s 
    ) 
    select ItemNumber = row_number() over(order by l.n1) 
         , Item  = substring(@pString, l.n1, l.l1) 
        from cteLen l; 
    go 
    

    분할 문자열 참조 :