如何将Q1和Q2组合成Q5(但工作!)? PLSE?我卡住了... SQL Server 2008 R2
请看看我到目前为止所尝试的内容:
- Q1执行时没有错误: DECLARE @RfDate日期 DECLARE @Description nvarchar(250) DECLARE @BAccount int SET @RfDate ='{Rf_Date}' SET @Description = {dbo.BankstatementLine_Description | type = string} SET @BAccount = {dbo.BankAccount_Id}
IF @RfDate <> ''
BEGIN
SELECT *
FROM
dbo.BankStatementLine
WHERE
Date >=@RfDate
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 =@BAccount
AND
IsDebit = 'true'
AND
Id NOT IN (select FkBankStatementLine from DocumentBankStatementLine)
END
- Q2执行时没有错误: DECLARE @RAmount浮动 SET @RAmount = {Rf_Amount}
IF @RAmount <>''
BEGIN
SELECT Amount
FROM dbo.BankStatementLine
WHERE Amount=@RAmount
END
ELSE
BEGIN
SELECT Amount
FROM dbo.BankStatementLine
WHERE Amount<>@RAmount
END
在X-Zero 的帮助下(命令描述我的角色比我的程序技能更好),我想出了以下查询,它实际上做了它需要做的事情,除了最后一个两个AND OR规则。 LIKE没有任何影响,如果我在@RfAccept字段中输入'PEKING',则应显示描述为“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
答案 0 :(得分:1)
...您似乎对(不完全)理解SQL有一些问题,而且它只能在一般用途中完成。这些“程序”通常(虽然并非总是)不必要。你没有列出你的RDBMS,所以我写的就好像是DB2(不包括语句参数),尽管大多数主要的RDBMS都能够按原样运行语句 。
-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))
-Q3似乎是Q1和Q2的组合(有点):
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:我不确定你是否可以实际嵌套if
语句(特别是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 JOIN
被认为是{{ 1}}子句谓词):
WHERE
嵌套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))
语句/子句总是略显危险,即使在普通命令式(Java,C#,C ++等)语言中也是如此。在SQL和类似的情况下,它可能只是完全错误。你好像在想一个强制性的程序员 - 学会用集(你的if
和WHERE
条款)思考,你会好多了。< / p>
<小时/> 编辑:
它没有返回您期望的结果,因为比较区分大小写。对于大多数其他编程语言来说,这也是正确的
作为旁注,执行JOIN
(带有前导LIKE '%<insertValueHere>'
)可以防止使用指标(因为优化器没有好方法知道列中的 where 价值出现)。将函数包装在函数中也不会有太大帮助,但我相信有一些方法可以创建“物化”/计算的指标,这样该值就已经可用了。
无论如何,这是适当的调整。请注意,如果列始终具有值(而不是null),则如果未提供输入参数,则无需进行比较。
%
当您输入的参数上写着“我不在乎它是什么,给我一切”时,不需要与该字段进行比较(并且可能会变得更好通过删除比较表现)。如果您仍然需要检查以确保该字段不为空或空白或其他内容,那么您做必须在某些时候检查它 - 在SQL中,或在获取结果集之后。
此外,如果您使用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 =''))
在字段内搜索,因为它包含多个值(作为分隔符/格式化列表或数据结构),您(很可能)会错误地设置表格;重新格式化以将列放入其自己的表中(嗯,_usually)。如果它是事物的一部分(比如在书名中搜索一个单词),你只需要考虑性能(好吧,有可能方法,但会导致设计有些古怪)
答案 1 :(得分:0)
看起来您正在使用SQL Server(通常有助于指定):
Amount = CASE WHEN @RAmount <> '' THEN @RAmount
WHEN @RAcAmount <> '' THEN @RacAmount
ELSE Amount END
是我认为你正在寻找的。如果第一个参数不为空,则使用它。如果第一个参数为空,而第二个参数不为,则使用第二个参数。如果两者都为空,则返回所有值。