“where”子句中的SQL开关/大小写
我试着四处寻找,但找不到任何能帮我的东西 我尝试在SQL中执行此操作:“where”子句中的SQL开关/大小写,sql,switch-statement,case,Sql,Switch Statement,Case,我试着四处寻找,但找不到任何能帮我的东西 我尝试在SQL中执行此操作: declare @locationType varchar(50); declare @locationID int; SELECT column1, column2 FROM viewWhatever WHERE CASE @locationType WHEN 'location' THEN account_location = @locationID WHEN 'area' THEN xxx_locat
declare @locationType varchar(50);
declare @locationID int;
SELECT column1, column2
FROM viewWhatever
WHERE
CASE @locationType
WHEN 'location' THEN account_location = @locationID
WHEN 'area' THEN xxx_location_area = @locationID
WHEN 'division' THEN xxx_location_division = @locationID
我知道我不应该在每一个结尾都加上“=@locationID”,但我甚至不能让语法接近正确。SQL一直在第一行抱怨我的“=”,当
我该怎么做呢?我认为这是表结构有缺陷的一个指标。也许不同的位置类型应该在不同的表中分开,这样您就可以进行更丰富的查询,还可以避免周围有多余的列
declare @locationType varchar(50);
declare @locationID int;
SELECT column1, column2
FROM viewWhatever
WHERE
@locationID =
CASE @locationType
WHEN 'location' THEN account_location
WHEN 'area' THEN xxx_location_area
WHEN 'division' THEN xxx_location_division
END
如果无法更改结构,以下类似操作可能会起作用:
SELECT
*
FROM
Test
WHERE
Account_Location = (
CASE LocationType
WHEN 'location' THEN @locationID
ELSE Account_Location
END
)
AND
Account_Location_Area = (
CASE LocationType
WHEN 'area' THEN @locationID
ELSE Account_Location_Area
END
)
等等。。。我们不能动态地改变查询的结构,但是我们可以通过使谓词自身相等来覆盖它
编辑:上面的建议当然更好,忽略我的建议。问题是,当SQL引擎计算表达式时,它会检查FROM部分以提取适当的表,然后检查WHERE部分以提供一些基本条件,因此,它无法正确评估要检查的列的动态条件 在检查谓词中的WHERE条件时,可以使用WHERE子句,例如
WHERE account_location = CASE @locationType
WHEN 'business' THEN 45
WHEN 'area' THEN 52
END
因此,在您的特定情况下,您需要将查询放入存储过程或创建三个单独的查询。给您
SELECT
column1,
column2
FROM
viewWhatever
WHERE
CASE
WHEN @locationType = 'location' AND account_location = @locationID THEN 1
WHEN @locationType = 'area' AND xxx_location_area = @locationID THEN 1
WHEN @locationType = 'division' AND xxx_location_division = @locationID THEN 1
ELSE 0
END = 1
没有案件陈述
SELECT column1, column2
FROM viewWhatever
WHERE
(@locationType = 'location' AND account_location = @locationID)
OR
(@locationType = 'area' AND xxx_location_area = @locationID)
OR
(@locationType = 'division' AND xxx_location_division = @locationID)
请尝试此查询。
以上职位的答复:
select @msgID, account_id
from viewMailAccountsHeirachy
where
CASE @smartLocationType
WHEN 'store' THEN account_location
WHEN 'area' THEN xxx_location_area
WHEN 'division' THEN xxx_location_division
WHEN 'company' THEN xxx_location_company
END = @smartLocation
试试这个:
WHERE (
@smartLocationType IS NULL
OR account_location = (
CASE
WHEN @smartLocationType IS NOT NULL
THEN @smartLocationType
ELSE account_location
END
)
)
尝试此查询。这很容易理解:
CREATE TABLE PersonsDetail(FirstName nvarchar(20), LastName nvarchar(20), GenderID int);
GO
INSERT INTO PersonsDetail VALUES(N'Gourav', N'Bhatia', 2),
(N'Ramesh', N'Kumar', 1),
(N'Ram', N'Lal', 2),
(N'Sunil', N'Kumar', 3),
(N'Sunny', N'Sehgal', 1),
(N'Malkeet', N'Shaoul', 3),
(N'Jassy', N'Sohal', 2);
GO
SELECT FirstName, LastName, Gender =
CASE GenderID
WHEN 1 THEN 'Male'
WHEN 2 THEN 'Female'
ELSE 'Unknown'
END
FROM PersonsDetail
当处于where条件时,OR运算符可以作为情况的替代
ALTER PROCEDURE [dbo].[RPT_340bClinicDrugInventorySummary]
-- Add the parameters for the stored procedure here
@ClinicId BIGINT = 0,
@selecttype int,
@selectedValue varchar (50)
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SELECT
drugstock_drugname.n_cur_bal,drugname.cdrugname,clinic.cclinicname
FROM drugstock_drugname
INNER JOIN drugname ON drugstock_drugname.drugnameid_FK = drugname.drugnameid_PK
INNER JOIN drugstock_drugndc ON drugname.drugnameid_PK = drugstock_drugndc.drugnameid_FK
INNER JOIN drugndc ON drugstock_drugndc.drugndcid_FK = drugndc.drugid_PK
LEFT JOIN clinic ON drugstock_drugname.clinicid_FK = clinic.clinicid_PK
WHERE (@ClinicId = 0 AND 1 = 1)
OR (@ClinicId != 0 AND drugstock_drugname.clinicid_FK = @ClinicId)
-- Alternative Case When You can use OR
AND ((@selecttype = 1 AND 1 = 1)
OR (@selecttype = 2 AND drugname.drugnameid_PK = @selectedValue)
OR (@selecttype = 3 AND drugndc.drugid_PK = @selectedValue)
OR (@selecttype = 4 AND drugname.cdrugclass = 'C2')
OR (@selecttype = 5 AND LEFT(drugname.cdrugclass, 1) = 'C'))
ORDER BY clinic.cclinicname, drugname.cdrugname
END
试试这个查询,它非常简单而且有用:它已经准备好执行了
USE tempdb
GO
IF NOT OBJECT_ID('Tempdb..Contacts') IS NULL
DROP TABLE Contacts
CREATE TABLE Contacts(ID INT, FirstName VARCHAR(100), LastName VARCHAR(100))
INSERT INTO Contacts (ID, FirstName, LastName)
SELECT 1, 'Omid', 'Karami'
UNION ALL
SELECT 2, 'Alen', 'Fars'
UNION ALL
SELECT 3, 'Sharon', 'b'
UNION ALL
SELECT 4, 'Poja', 'Kar'
UNION ALL
SELECT 5, 'Ryan', 'Lasr'
GO
DECLARE @FirstName VARCHAR(100)
SET @FirstName = 'Omid'
DECLARE @LastName VARCHAR(100)
SET @LastName = ''
SELECT FirstName, LastName
FROM Contacts
WHERE
FirstName = CASE
WHEN LEN(@FirstName) > 0 THEN @FirstName
ELSE FirstName
END
AND
LastName = CASE
WHEN LEN(@LastName) > 0 THEN @LastName
ELSE LastName
END
GO
这对我有用
创建表每校准年整数,校准每整数
在每校准年中插入校准值20,1,20,2,20,3,20,4,20,5,20,6,20,7,20,8,20,9,20,10,20,11,20,12,
99,1 , 99,2 , 99,3 , 99,4 , 99,5 , 99,6 , 99,7 , 99,8 , 99,9 , 99,10 , 99,11 , 99,12
4位数的世纪由规则决定,如果年份为50或以上,则世纪为1900,否则为2000
给定两个标记开始和结束周期的6位数周期(如四分之一),返回该范围内的行
-2020年第一季度
在202001和202003之间,如果校准年份>50,则选择*从每校准年份,然后选择1900 ELSE 2000结束+校准年份*100+每校准年份
-一九九九年第四季
在199910年和199912年之间,如果校准年份>50,则选择*FROM PER_CAL,然后选择1900 ELSE 2000 END+CAL_YEAR*100+CALU PER
我不认为这是一个有缺陷的桌子结构。该表是以这种方式设置的,因此具有无限多的父/子关系是自引用。相信我,这是故意的。我不想把我的表结构改成只使用switch语句。TomH在下面对您的回复的评论中指出,您的SQL格式不正确。我在SQLServer2005中测试了我的,效果很好。为什么需要@呢?它们是做什么的?@表示t-sql中的变量,如果没有@,@locationID将被解释为一个列名。好吧,我会把它写成SELECT column1,视图中的第2列无论@locationType='location'和account\u location=@locationID或@locationType='area'和xxx\u location\u area=@locationID或@locationType='division'和xxx\u location\u division=@locationID这都是一个很好的例子,如果你想使用不同类型的where子句,比如在第一个子句上使用int,在第二个子句上使用nvarchar,我更喜欢这个方法代码清晰,非常好。对于Bob Probst,解决方案不起作用。谢天谢地,当满足条件后Case语句退出时,这将给出一个稍微不同的结果,但是OR语法将计算所有possibilities@tember即使SQL是一种过程语言,如果第一个OR为true,则表达式的其余部分也不会得到计算。由于SQL是一种声明性语言,您如何知道DBM将对所有ORs进行求值?诚恳的问题,我不明白。在SQL中,表达式的其余部分是用OR语法计算的。试试这个,它不会让我包含@符号-如果你想测试它,你必须纠正它:declare var varchar5 set var='0'选择2/var,其中var 0或ISNUMERICvar=1。我希望条件退出,因为var等于0,但它会继续检查它是否为数值,事实上,因此,该语句返回一个错误。在我的例子中,该语句对类型的每个值都有一个不同的比较运算符。如果@locationType='location'开始选择column1,则最好还是声明@locationType NVARCHAR50='youchoose',如果@locationType='location'开始选择column1,视图中的第2列无论在何处帐户\u位置=@locationID结束如果@locationType='area'开始选择第1列,第2列
从视图中,无论xxx\u location\u area=@locationID END,如果@locationType='division'开始选择column1,第2列FROM view WHERE xxx_location_division=@locationID ENDTo将来读到这篇文章的人:这与上面@bob prost的公认答案是一样的:否决,因为我不明白如何在给定的字符串之间进行选择,即“location”、“area”,对阅读此答案的人进行“分组”:这与上面@bob prost接受的答案相同:因为这个原因投了反对票。投反对票是因为这个答案与问题无关。问题是如何在WHERE子句上使用CASE,而不是如何在所选列上使用CASE。
CREATE PROCEDURE [dbo].[Temp_Proc_Select_City]
@StateId INT
AS
BEGIN
SELECT * FROM tbl_City
WHERE
@StateID = CASE WHEN ISNULL(@StateId,0) = 0 THEN 0 ELSE StateId END ORDER BY CityName
END
USE tempdb
GO
IF NOT OBJECT_ID('Tempdb..Contacts') IS NULL
DROP TABLE Contacts
CREATE TABLE Contacts(ID INT, FirstName VARCHAR(100), LastName VARCHAR(100))
INSERT INTO Contacts (ID, FirstName, LastName)
SELECT 1, 'Omid', 'Karami'
UNION ALL
SELECT 2, 'Alen', 'Fars'
UNION ALL
SELECT 3, 'Sharon', 'b'
UNION ALL
SELECT 4, 'Poja', 'Kar'
UNION ALL
SELECT 5, 'Ryan', 'Lasr'
GO
DECLARE @FirstName VARCHAR(100)
SET @FirstName = 'Omid'
DECLARE @LastName VARCHAR(100)
SET @LastName = ''
SELECT FirstName, LastName
FROM Contacts
WHERE
FirstName = CASE
WHEN LEN(@FirstName) > 0 THEN @FirstName
ELSE FirstName
END
AND
LastName = CASE
WHEN LEN(@LastName) > 0 THEN @LastName
ELSE LastName
END
GO