Gib*_*ron 12 sql t-sql sql-server sql-server-2008
我创建了一个简单的例子(希望比我的实际数据更有趣)来更好地表达我的问题:
CREATE TABLE SUPER_HERO
( ID INT,
NAME VARCHAR(50)
)
INSERT INTO SUPER_HERO VALUES (1, 'Storm')
INSERT INTO SUPER_HERO VALUES (2, 'Silver Surfer')
INSERT INTO SUPER_HERO VALUES (3, 'Spider Man')
CREATE TABLE SKILL
( ID INT,
NAME VARCHAR(50)
)
INSERT INTO SKILL VALUES (1, 'Flight')
INSERT INTO SKILL VALUES (2, 'Weather Control')
INSERT INTO SKILL VALUES (3, 'Super Speed')
CREATE TABLE SUPER_HERO_SKILL
( SUPER_HERO_ID INT,
SKILL_ID INT
)
INSERT INTO SUPER_HERO_SKILL VALUES (1, 1) --Storm has Flight
INSERT INTO SUPER_HERO_SKILL VALUES (1, 2) --Storm has Weather Control
INSERT INTO SUPER_HERO_SKILL VALUES (2, 1) --Silver Surfer has Flight
INSERT INTO SUPER_HERO_SKILL VALUES (2, 3) --Silver Surfer has Super Speed
INSERT INTO SUPER_HERO_SKILL VALUES (3, 3) --Spider Man has Super Speed
Run Code Online (Sandbox Code Playgroud)
错误查询的示例(未显示所需结果):
DECLARE @DELIMITER CHAR = ','
DECLARE @CSV_STRING VARCHAR(20) = '1,3'
SELECT
SUPER_HERO_NAME = SUPER_HERO.NAME,
SKILL_NAME = SKILL.NAME
FROM
SUPER_HERO
JOIN SUPER_HERO_SKILL ON SUPER_HERO_SKILL.SUPER_HERO_ID = SUPER_HERO.ID
JOIN SKILL ON SUPER_HERO_SKILL.SKILL_ID = SKILL.ID
JOIN dbo.Split(@CSV_STRING, @DELIMITER) SPLIT ON SPLIT.ITEMS = SKILL.ID
Run Code Online (Sandbox Code Playgroud)
我想看到的:
当DECLARE @CSV_STRING VARCHAR(20) = '1,3'我只看到"银色冲浪者"时,因为他是唯一一个同时拥有与飞行和超速相关的技能1和3的人.
当DECLARE @CSV_STRING VARCHAR(20) = '1,2,3'我不应该在我的宇宙中看到任何英雄,因为没有定义所有三种技能列出.
必须有一些我想念的简单.我尝试过多种不同的方式构建查询.我在这里提出了最简单的形式,以免使问题的表达复杂化.
注意:我使用一个函数作为基于传入的分隔符的Split.
使用以下拆分器函数返回int列.所以很容易检查HAVING子句中的计数.
CREATE FUNCTION [dbo].[DelimitedParamParser]( @DelimitedIds VARCHAR(MAX), @Delimiter CHAR(1))
RETURNS @IdsTable
TABLE ( Id INT )
AS BEGIN
DECLARE @Length INT,
@Index INT,
@NextIndex INT
SET @Length = DATALENGTH(@DelimitedIds)
SET @Index = 0
SET @NextIndex = 0
WHILE (@Length > @Index )
BEGIN
SET @NextIndex = CHARINDEX(@Delimiter, @DelimitedIds, @Index)
IF (@NextIndex = 0 ) SET @NextIndex = @Length + 2
INSERT @IdsTable SELECT SUBSTRING( @DelimitedIds, @Index, @NextIndex - @Index )
SET @index = @nextindex + 1
END
RETURN
END
Run Code Online (Sandbox Code Playgroud)
这是有效的,请记住最后给出一个额外的逗号.
DECLARE @DELIMITER CHAR = ','
DECLARE @CSV_STRING VARCHAR(20) = '1,3,'
SELECT Distinct SUPER_HERO.NAME, SKILL.NAME
FROM
SUPER_HERO
INNER JOIN SUPER_HERO_SKILL ON SUPER_HERO_SKILL.SUPER_HERO_ID = SUPER_HERO.ID
INNER JOIN SKILL ON SUPER_HERO_SKILL.SKILL_ID = SKILL.ID
WHERE SUPER_HERO.ID IN
(
SELECT SUPER_HERO_SKILL.SUPER_HERO_ID
FROM
SUPER_HERO
INNER JOIN SUPER_HERO_SKILL ON SUPER_HERO_SKILL.SUPER_HERO_ID = SUPER_HERO.ID
INNER JOIN SKILL ON SUPER_HERO_SKILL.SKILL_ID = SKILL.ID
INNER JOIN DelimitedParamParser(@CSV_STRING, @DELIMITER) SPLIT ON SPLIT.ID = SUPER_HERO_SKILL.SKILL_ID
GROUP BY SUPER_HERO_SKILL.SUPER_HERO_ID
HAVING COUNT(DISTINCT(SUPER_HERO_SKILL.SKILL_ID)) = (SELECT COUNT(DISTINCT(Id)) FROM DelimitedParamParser(@CSV_STRING, @DELIMITER))
)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
507 次 |
| 最近记录: |