SQL决策语句

时间:2013-08-20 19:08:03

标签: sql-server sql-server-2008 tsql

我正在尝试创建一个决策声明,以确定5个变量(@ skill1,@ skill2,@ skill3,@ skill4,@ skill5)是否为空或空。

people_skills表包含每个人的不同技能。因此,一个人可能有超过1条记录。 lkp_skills包含这些技能的名称。

基于5个不同的技能领域,我想忽略空字符串。我还想在lkp_skills表中搜索字符串。如果变量与该表的s.skill字段匹配,那么我希望它返回该记录。如果有多种技能,那么我希望它能够返回具有这两种技能的记录。

这样做的最佳方式是什么?

DECLARE @zip char(5) = '61265',         -- Zip Code 
        @skill1 varchar(50) = 'sql',  -- Job Skill 1
        @skill2 varchar(50) = 'css',  -- Job Skill 2
        @skill3 varchar(50) = '',  -- Job Skill 3
        @skill4 varchar(50) = '',  -- Job Skill 4
        @skill5 varchar(50) = '',  -- Job Skill 5
        @distance int = 5           -- Distance in miles

SELECT p.people_id, p.first_name, p.last_name, p.address_1, p.address_2, p.city, p.[state],
       p.zip_code, (dbo.sp_getDistance(@zip, zip_code)) AS miles, s.skill
FROM people p
  INNER JOIN people_skills ps ON ps.people_id = p.people_id
  INNER JOIN lkp_skills s ON ps.skill_id = s.skill_id
WHERE (ISNUMERIC(p.zip_code) = 1 AND LEN(RTRIM(LTRIM(p.zip_code))) = 5)
       AND p.ROLE_ID <= 4 
       AND ((dbo.sp_getDistance(@zip, zip_code)) <= @distance)
       AND

       -- DECISION STATEMENT GOES HERE --

ORDER BY miles

2 个答案:

答案 0 :(得分:3)

如果您认为没有2个技能具有相同的名称,那么此查询将返回拥有您所有技能的所有人:

DECLARE @zip char(5), @distance int
DECLARE @Skill1 varchar(50), @Skill2 varchar(50), @Skill3 varchar(50), @Skill4 varchar(50), @Skill5 varchar(50)

SET @zip = '61265'
SET @distance = 5
SET @skill1 = 'sql'
SET @skill2 = 'css'

-- Count how many skills we should search for...
DECLARE @SkillCount int
SET @SkillCount = 0
IF @skill1 IS NOT NULL AND @skill1 != '' SET @SkillCount = @SkillCount + 1
IF @skill2 IS NOT NULL AND @skill2 != '' SET @SkillCount = @SkillCount + 1
IF @skill3 IS NOT NULL AND @skill3 != '' SET @SkillCount = @SkillCount + 1
IF @skill4 IS NOT NULL AND @skill4 != '' SET @SkillCount = @SkillCount + 1
IF @skill5 IS NOT NULL AND @skill5 != '' SET @SkillCount = @SkillCount + 1


SELECT p.people_id, p.first_name, p.last_name, p.address_1, p.address_2, p.city, p.[state],
       p.zip_code, (dbo.sp_getDistance(@zip, zip_code)) AS miles
FROM people p
WHERE (ISNUMERIC(p.zip_code) = 1 AND LEN(RTRIM(LTRIM(p.zip_code))) = 5)
    AND p.ROLE_ID <= 4 
    AND ((dbo.sp_getDistance(@zip, zip_code)) <= @distance)
    AND p.people_id IN (
        -- Get the list of people who have all of the needed skills
        SELECT ps.people_id
        FROM people_skills ps
            INNER JOIN lkp_skills s
            ON ps.skill_id = s.skill_id
        WHERE s.name IN ( @skill1, @skill2, @skill3, @skill4, @skill5 )
        GROUP BY ps.people_id
        -- This is the key.  This filters the list of people to make
        -- sure that the person has ALL of the skills.
        HAVING COUNT(*) = @SkillCount
    )
ORDER BY miles

另请注意,距离搜索中的WHERE子句表达式不保证按您指定的顺序运行。例如,如果sp_getDistance如果zip_code不是数字则抛出错误,那么您的查询现在可以正常工作,但在将来的某个时候,查询优化器可能会更改WHERE子句的顺序而您会开始出错。

答案 1 :(得分:0)

您可以在WHERE子句中使用CASE语句,或者只是在存储过程中使SQL动态化(当然,您必须处理安全性)。

using CASE in T-SQL in the where clause?

OR

DECLARE @SQL varchar(max);

SET @SQL = 'SELECT ......';

IF LEN(@Skill1) > 0 
BEGIN
    SET @SQL = @SQL + '<your statement>'
END