2012-11-18 4 views
0

저장 프로 시저에 전달 된 일부 매개 변수를 기반으로 데이터를 선택하려고합니다. 내가 나이 문제는, 내가 이런 일을하려고하고 있습니다 다음, 내 저장 프로 시저 매개 변수 @Age = 1 다음 나는 18-15 사이의 나이를 선택하는 경우SQL Server : SELECT 및 CASE

19 @Age = 2을 - ... 25, 분명히 이것은 잘못된 것입니다, 사람 도울 수있다. 감사합니다 : 나는이 생각

SELECT 
    User 
FROM 
    [Member] m 
WHERE 
    ((m.Gender = @Gender) or @Gender IS NULL) 
    and ((DATEDIFF(hour,m.DOB,GETDATE())/8766) Between 
     CASE  
     WHEN @Age = 1 THEN (SELECT DATEDIFF(hour, m.DOB, GETDATE())/8766 WHERE (SELECT DATEDIFF(hour, m.DOB, GETDATE())/8766) between 15 and 18) 
     WHEN @Age = 2 THEN (SELECT DATEDIFF(hour,m.DOB,GETDATE())/8766 WHERE (SELECT DATEDIFF(hour,m.DOB,GETDATE())/8766) between 19 and 25) 
     END) 
+0

연령을 처리하는 더 좋은 방법은 일반적으로 오늘 날짜에 필요한 (음수) 년을 더하고이를 'DOB' 열과 직접 비교하는 것입니다. 그것은 윤년에 이상한 퍼지를하지 않아도되고 잠재적으로'DOB' 칼럼의 인덱스를 사용할 수 있습니다. –

답변

4

은 당신이 무엇을 (아마 불필요한 괄호 포함) 후 : 당신이 절을 많이 가지고있는 경우에

Select 
    [User] 
From 
    [Member] m 
Where (
    (m.Gender = @Gender) or 
    @Gender Is Null 
) And (
    (@Age = 1 And DateDiff(hour, m.Dob, GetDate())/8766 Between 15 and 18) Or 
    (@Age = 2 And DateDiff(hour, m.Dob, GetDate())/8766 Between 19 and 25) 
) 

, 그것뿐만 쉽게 읽을 수 있습니다

더 나은
Select 
    [User] 
From 
    [Member] m 
    Inner Join (
     Select 
     MemberID, 
     DateDiff(hour, m.Dob, GetDate())/8766 As Years 
     From 
     [Member] 
    ) As y 
    On m.MemberID = y.MemberID 
Where (
    (m.Gender = @Gender) or 
    @Gender Is Null 
) And (
    (@Age = 1 And y.Year Between 15 and 18) Or 
    (@Age = 2 And y.Year Between 19 and 25) 
) 

, 별도의 테이블에 범위를 추가 할 수 있습니다 (A MEMBERID 기본 키를 가정) AgeRanges

라는
+-------+------------+----------+ 
| AgeID | StartYears | EndYears | 
+-------+------------+----------+ 
|  1 |   15 |  18 | 
|  2 |   19 |  25 | 
| ... |  ... |  ... | 
+-------+------------+----------+ 

Select 
    [User] 
From 
    [Member] m 
    Inner Join 
    [AgeRanges] a 
    On DateDiff(hour, m.Dob, GetDate())/8766 Between a.StartYears and a.EndYears And 
     a.AgeID = @Age 

또한 회원 테이블에서 DateDiff(hour, m.Dob, GetDate())/8766 계산 된 열을 사용하면 작업을 단순화하고 성능이 문제가 될 경우 색인 생성을 수행 할 수 있습니다.

+0

This. 범위 테이블은 작업을 훨씬 단순하게 만듭니다. 궁금한 점 (@OP) - Hours/8766을 사용하는 이유는 무엇입니까? DATEDIFF (year, date1, date2)가 작동해야합니다. 실험 해봐야한다. (SQLServer를 실행하면 20 초 만에 실행이 가능할 것이다.) 그러나 정수가 반올림 됨으로써 19 번째 생일이되기 전날의 사람이 18로 계산된다. – sebt

+0

@ sebt - 'DATEDIFF (year, ...') 문제는 날짜의 연도 구성 요소가 두 값 사이에서 변경된 횟수를 계산하므로 2011 년 12 월 31 일에 태어난 사람이 1 살이라는 것을보고합니다. –

+0

@Damien_The_Unbeliever : 네가 맞아. 내가 지금 시험해 볼 수있는 기계가 아니지만, 나는 그런 것을 기억한다. 내가 기억할 수있는 가장 좋은 해결책은 GETDATE부터 DATEADD를 반복하는 것이다 (year, -1, [this])에 도달 할 때까지 반복되고, 루프를 세고 (+ -1 오류와 조심스럽게) DATEDIFF (hour, DOB, GETDATE)/8766의 문제는 윤년을 평균 매년 6 시간마다보다는 +6 시간 (.... 기억할 수는 없지만)! 오히려 나는 내부 날짜 처리 루틴에 도약을 도웁시다 ... – sebt