gpt4 book ai didi

sql - 如何构建查询以仅提供与 T-SQL 中 CSV ID 列表中的所有值匹配的行

转载 作者:行者123 更新时间:2023-12-02 08:46:50 24 4
gpt4 key购买 nike

我创建了一个简单的示例(希望比我的实际数据更有趣)来更好地表达我的问题:

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

错误查询示例(未显示所需结果):

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

我想看到什么:
DECLARE @CSV_STRING VARCHAR(20) = '1,3' 时,我应该只看到“Silver Surfer”,因为他是唯一同时拥有与飞行和 super 速度相关的技能 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

这有效,请记住在末尾添加一个额外的逗号。

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))
)

关于sql - 如何构建查询以仅提供与 T-SQL 中 CSV ID 列表中的所有值匹配的行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7492699/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com