2011-12-08 2 views
0

Q1과 Q2를 Q5와 같은 someting으로 결합하는 방법 (하지만 작동!)? 계획?Sql은 여러 매개 변수로 WHEN 및 IF 문을 결합합니다.

--Q1 오류없이 실행 않습니다 : DECLARE @RfDate 날짜 DECLARE의 @description 나는 ... SQL 서버 2008 R2

지금까지 시도했다 보려면 다음을 보면 붙어 NVARCHAR (250) DECLARE는 SET를 int로 @BAccount @RfDate = '{Rf_Date}' SET @description = {dbo.BankstatementLine_Description | 종류 = 문자열} SET의 @BAccount = {dbo.BankAccount_Id}

IF @RfDate <> '' 
     BEGIN 
      SELECT * 
      FROM 
       dbo.BankStatementLine 
      WHERE 
       Date >[email protected] 
      AND 
       FkBankAccount = @BAccount 
      AND 
       IsDebit = 'true' 
      AND 
       Id NOT IN (select FkBankStatementLine from DocumentBankStatementLine) 
     END              
    ELSE 
     BEGIN 
      SELECT * 
      FROM 
       dbo.BankStatementLine 
      WHERE 
       Date <> @RfDate 
      AND 
       FkBankAccount [email protected] 
      AND 
       IsDebit = 'true' 
      AND 
       Id NOT IN (select FkBankStatementLine from DocumentBankStatementLine) 
     END 
오류없이 실행 않습니다

--Q2가 : DECLARE은 = {Rf_Amount}

IF @RAmount <>'' 
     BEGIN 
      SELECT Amount 
      FROM  dbo.BankStatementLine 
      WHERE [email protected] 
     END 
    ELSE 
     BEGIN 
      SELECT Amount 
      FROM  dbo.BankStatementLine 

      WHERE Amount<>@RAmount 
      END 

X-제로 의 도움 후 SET의 @RAmount을 떠 @RAmount (필수는 더 나은 내 캐릭터를 설명 그때 내 프로그램 기술 btw), 내가 실제로 마지막으로 두 가지 AND OR 규칙을 제외하고, 할 필요가 다음 쿼리를 생각해 냈어. 등 .....

을 내가 필드 @RfAccept에 '북경'을 입력하면, 설명 "0111111111 GPPeking"아 파크 항목이 제시되어야한다, 어떤 영향이없는,하지만하지 않습니다되어

DECLARE @RfDate date 
DECLARE @BAccount int 
DECLARE @RfAmount decimal 
DECLARE @RfAcAmount float 
DECLARE @RfKenmerk nvarchar(250) 
DECLARE @RfAccept nvarchar(250) 
SET @RfDate = '{Rf_Date}' 
SET @BAccount = {dbo.BankAccount_Id} 
SET @RfAmount = {Rf_Amount} 
SET @RfAcAmount = {Rf_AccAmount} 
SET @RfKenmerk = {Rf_Betalingskenmerk|type=string} 
SET @RfAccept = {Rf_Acceptgiro|type=string} 

     SELECT * 
     FROM 
      dbo.BankStatementLine 
     WHERE -- All statements can have a value or ''. All statements are not mandatory. 
       isDebit = 1 
     AND Id NOT IN (select FkBankStatementLine from DocumentBankStatementLine) 

     AND fkBankAccount = {dbo.bankAccount_Id} 

     AND ((Date = @RfDate AND @RfDate <> '') 
     OR (Date <> @RfDate AND @RfDate = '')) 

     AND ((Amount = @RfAmount AND @RfAmount <> '') 
     OR (Amount <> @RfAmount AND @RfAmount = '')) 

     AND ((Amount = @RfAcAmount AND @RfAcAmount <> '') 
     OR (Amount <> @RfAcAmount AND @RfAcAmount = '')) 

     AND((Description LIKE '%@RfAccept%' AND @RfAccept<>'')--When Rf_Acceptgiro has a value, the value must be part of the field Description. 
     OR (Description <> @RfAccept AND @RfAccept ='')) --OR Return all Description rules 

     AND((Description LIKE '%@RfKenmerk%' AND @RfKenmerk<>'')--When Rf_Kenmerk has a value, the value must be part of the field Description. 
     OR (Description <> @RfKenmerk AND @RfKenmerk =''))--OR Return all Description rules 

Amount = CASE WHEN @RAmount <> '' THEN @RAmount 
       WHEN @RAcAmount <> '' THEN @RacAmount 
       ELSE Amount END 

난 당신이 찾고있는 생각이다 : 당신이 (이것은 일반적으로 지정하는 데 도움) SQL Server와 함께 작업하는 것처럼

+0

코드는 따르기가 어렵고 SQL이 지원하지 않는 코드를 시도하고 있습니다. 당신이 달성하고자하는 것을 보여줄 수 있다면 샘플 날짜와 함께, 더 많은 사람들이 당신을 도울 수 있어야합니다. ... – Sparky

+0

"Q5"에서 한 즉각적인 코멘트는 IF/ELSE/ELSE를 보는 것 같습니다. 구조? – BRFennPocock

+0

* 알고 있으며 유감입니다. 나는 지독한 일에 대해 몇 시간 동안 일하고 있었고 곧 독감에 걸렸다. 그게 내가 웹에 질의를 바로 써서 오늘 아침에 새 표정을 지었다. 봐 주셔서 감사합니다. X-Zero (도움을 주셔서 감사합니다.)의 도움을 받아 쿼리를 받았지만 여전히 해결해야 할 한 가지는 ... – Bouwplaats

답변

1

... SQL을 완전히 이해하지 못하는 문제가있는 것 같습니다. 일반적인 용도로만 수행 할 수 있습니다. 이러한 종류의 '절차'는 이고 일반적으로 (항상은 아니지만)은 불필요합니다. RDBMS를 나열하지 않았으므로 대부분의 주요 RDBMS가 문 을 주로 그대로 사용할 수 있지만 DB2 (명령문 매개 변수 제외)처럼 작성합니다.

-Q1은 단순히 그래서 같이 다시 쓸 수있다 :

SELECT a.* -- note, make sure to list all columns in actual query, '*' is bad form 
FROM dbo.BankStatementLine as a 
EXCEPTION JOIN DocumentBankStatementLine as b 
ON b.fkBankStatementLine = a.id -- this is your 'NOT IN' statement 
WHERE a.isDebit = 'true' -- this is really bad; usea boolean type if available 
         -- otherwise, use `int`/`char` 1/0, with check constraints 
AND a.fkBankAccount = {dbo.bankAccount_id} 
AND (({Rf_Date} IS NOT NULL AND a.Date >= {Rf_Date}) -- please name 'a.date' better... 
    OR ({Rf_Date} IS NULL AND a.Date IS NULL)) -- and use `date` types, and -null- 

-Q2 같은 일반 원칙을 따른다 (이 무의미 보이더라도, 당신은 이미 양을 알고) :

SELECT amount -- it's -really- bad to use `float` types for money 
       -- use `decimal` or `int` (cents) types instead 
FROM dbo.BankStatementLine 
WHERE (({Rf_Amount} IS NOT NULL AND amount = {Rf_Amount}) 
     OR ({Rf_Amount} IS NULL AND amount IS NULL)) 

을 -

SELECT a.* 
FROM dbo.BankStatementLine as a -- unless there's a -need- to query a specific 
         -- schema, leave it off; you'll get a bit of flexibility 
EXCEPTION JOIN DocumentBankStatementLine as b 
ON b.fkBankStatementLine = a.id 
WHERE a.isDebit = 'true' 
AND a.fkBankAccount = {dbo.bankAccount_Id} -- this seems like a table name? 
AND (({Rf_Date} IS NOT NULL AND a.Date >= {Rf_Date}) 
    OR ({Rf_Date} IS NULL AND a.Date IS NULL)) 
AND (({Rf_Amount} IS NOT NULL AND amount = {Rf_Amount}) -- didn't know what you 
    OR ({Rf_AccAmount} IS NOT NULL AND amount = {Rf_AccAmount})) -- actually wanted 
      -- But `null`s don't compare to anything, so... 

- Q4 : Q3는 Q1과 (일종의) Q2의 조합이 될 것으로 보인다 잘 모르겠어요 당신이 둥지 0 실제로 수 그 방법(특히 Amount-(IF @RAmount <> '') 라인, 그리고 확실히 이 아니어야합니다.주문이 중요한지 여부는 Q3 때문에 불분명합니다. 그래서 나는 그것이라고 가정했습니다. 대신 시도 (즉이, 그리고 원래 버전을 유의하시기 바랍니다 만있을 경우 하나 개의 행이 반환 일) :

SELECT * 
FROM dbo.BankStatementLine 
WHERE amount = COALESCE({RF_Amount}, {RfAccAmount}, (SELECT amount 
                FROM dbo.BankStatementLine 
                WHERE amount IS NOT NULL)) 

-Q5는 Q3과 Q1의 일부 이상한 괴상 집적 될 것으로 보인다. 같은 다시 쓰기 규칙은 비록 적용 ... 그리고 당신은 Q2와 Q1을 결합 할 경우, 단순히 함께 추가 WHERE 절에서 누락 된 술어 (우리의 목적을 위해, EXCEPTION JOINWHERE 절 술어로 간주됩니다) :

SELECT a.* 
FROM dbo.BankStatementLine as a 
EXCEPTION JOIN DocumentBankStatementLine as b 
ON b.fkBankStatementLine = a.id 
WHERE a.isDebit = 'true' 
AND a.fkBankAccount = {dbo.bankAccount_Id} 
AND (({Rf_Date} IS NOT NULL AND a.Date >= {Rf_Date}) 
    OR ({Rf_Date} IS NULL AND a.Date IS NULL)) 
AND (({Rf_Amount} IS NOT NULL AND amount = {Rf_Amount}) 
     OR ({Rf_Amount} IS NULL AND amount IS NULL)) 

중첩 if 문/절은 항상 명령형 (Java, C#, C++ 등) 언어에서도 약간 위험합니다. SQL과 유사하게, 그것은 아마도 단순한 잘못입니다. 당신은 명령형 프로그래머처럼 생각하고있는 것 같습니다 - 을 생각하면 (귀하의 WHEREJOIN 절)을 설정하는 것이 훨씬 나을 것입니다.


편집 : 비교는 대소 문자를 구분하기 때문에

그것은 당신이 기대하는 결과를 반환 아니에요. 이것은 대부분의 다른 프로그래밍 언어에서도 마찬가지입니다.
LIKE '%<insertValueHere>' (선두가 % 인)을 사용하면 색인자가 사용되지 않습니다 (값이 나타나는 열에서 인 을 알 수있는 좋은 방법이 없기 때문에). 함수에서 열을 감싸는 것도 도움이되지 않지만, 이미 값을 사용할 수 있도록 'materialized'/ computed indicies를 만드는 방법이 있다고 믿습니다.

어쨌든 여기에 적절한 조정이 있습니다. 열에 항상 값 (null과 반대)이 있으면 입력 매개 변수가 제공되지 않으면 비교를 수행 할 필요가 없습니다. 당신이라는 매개 변수를 입력 할 때

DECLARE @RfDate date 
DECLARE @BAccount int 
DECLARE @RfAmount decimal 
DECLARE @RfAcAmount float 
DECLARE @RfKenmerk nvarchar(250) 
DECLARE @RfAccept nvarchar(250) 
SET @RfDate = '{Rf_Date}' 
SET @BAccount = {dbo.BankAccount_Id} 
SET @RfAmount = {Rf_Amount} 
SET @RfAcAmount = {Rf_AccAmount} 
SET @RfKenmerk = {Rf_Betalingskenmerk|type=string} 
SET @RfAccept = {Rf_Acceptgiro|type=string} 

SELECT * 
FROM dbo.BankStatementLine 
WHERE isDebit = 1 -- Thank you, this is much better. If numeric, add check constraint. 
AND Id NOT IN (select FkBankStatementLine from DocumentBankStatementLine) 
       -- I am unsure of the performance of this relative to other options 
AND fkBankAccount = {dbo.bankAccount_Id} 
-- Assuming this is an actual date field, non-nullable, you don't need the second comparison 
AND ((Date = @RfDate AND @RfDate <> '') 
    OR (@RfDate = '')) 
-- Don't store amounts as strings, just don't... 
-- Comparison removed for reason above. 
AND ((Amount = @RfAmount AND @RfAmount <> '') 
    OR (@RfAmount = '')) 
-- See notes above 
AND ((Amount = @RfAcAmount AND @RfAcAmount <> '') 
    OR (@RfAcAmount = '')) 
-- If you want all rules/whatever, then... 
-- If it's case insensitive, it's best to -store- it that way. Otherwise, wrap in function 
AND((UPPER(Description) LIKE '%' || UPPER(@RfAccept) || '%' AND @RfAccept<>'') 
    OR (@RfAccept ='')) 
-- Same thing here too. 
AND((Description LIKE '%@RfKenmerk%' AND @RfKenmerk<>'') 
    OR (@RfKenmerk ='')) 

분야와 비교가 필요하지 않습니다, "나는 그것이 무엇인지 상관 없어를, 나에게 모든 것을 제공"(당신은 더 나은 성능을 얻을 수 있습니다 비교를 제거함으로써). 필드가 null 또는 공백이 아닌지 계속 확인해야한다면 에서 수행하십시오. SQL에서 또는 결과 세트를 가져온 후 어느 시점에서 확인해야합니다.
또한 필드에 LIKE '%whatever'으로 검색하는 경우 여러 값 (구분 기호/형식 목록 또는 데이터 구조)이 포함되어 있기 때문에 테이블을 잘못 설정했을 가능성이 큽니다. 열을 자신의 테이블에 넣으려면 다시 포맷해야합니다 (보통, 보통). 그것이 책 제목에서 단어를 검색하는 것과 같은 일의 일부라면, 실적이 좋을뿐입니다 (글쎄, 어쩌면 방법이 있지만 다소 엉뚱한 디자인이됩니다).

+0

광범위한 답변과 설명에 감사드립니다. 나는이 문제에 대해 SQL Server 2008R2를 사용하고 있습니다. 그리고 네, SQL을 이해하는 데 심각한 문제가 있지만 배우려합니다. 게다가, 여기 왜 너희들이 왔는가 ... ;-). 모든 것은 지금 원래의 ​​질문에 게시 된 하나의 어리 석음을 제외하고는 작동합니다 ... – Bouwplaats

+0

* "금액을 문자열로 저장하지 마십시오. 그냥하지 마세요."* 알지만, 그 이유는 다음과 같습니다. 데이터 유형을 변환하는 중 오류가 발생했습니다. varchar를 숫자로. 이것이 내가 문자열을 사용하는 이유입니다 ... DB에 오류가있는 것 같습니다. 나는 당신의 예를 빨리 시험해 볼 것입니다! 고마워요! – Bouwplaats

+0

@Bouwplaats - 그건 당신이 어딘가 잘못된 데이터를 가지고 있다는 증거입니다. 번호를 저장하는 방법과 방법에 따라, 이것은 어느 시점에서 당신을 물기 때문에 되돌아 올 수 있습니다. 해당 데이터를 찾아 수정하십시오 ** (여전히 문자열로 저장하더라도). 문자가 나쁘기 때문에 숫자 값을 저장하는 데에는 여러 가지 이유가 있지만, 재미있는 점은''100 ''은''8 "'또는''8"'보다 작지 만 (''008 "'보다 작지는 않지만 ''1000 ''을 저장해야한다면 어떻게됩니까?). –

0

보인다. 첫 번째 매개 변수가 비어 있지 않으면 사용하십시오. 첫 번째 매개 변수가 비어 있고 두 번째 매개 변수가 비어 있으면 두 번째 매개 변수를 사용하십시오. 둘 다 비어 있으면 모든 값을 반환합니다.

+0

친애하는 스튜어트, 노력에 감사드립니다.네, 실제로 SQL 서버. 위의 내용을 확인하십시오. 더 부드럽게 만들 수 있다면 ... – Bouwplaats

관련 문제