我有一个包含关联数据的表。它有三列SubjectId,StudentId和Rank。它是一个多对多关系表。我需要找到对应于排名顺序的给定StudentId列表的SubjectId。
如果订单不重要,我会做类似的事情
SELECT SubjectId
FROM mytable
WHERE StudentId IN (a,b,c) --This is the 'input'. I want order here to make a difference by matching to 'rank' but in this version it doesn't
GROUP BY SubjectId
HAVING COUNT(1) = 3
这也将返回具有学生等级的SubjectIds(a,c,b),(b,c,a)等。
如果a,b,c的顺序很重要,我该如何做同样的事?
修改:包含样本数据和预期结果
示例数据
SubjectId | StudentId | Rank
1|a|2
1|c|1
1|b|3
2|c|1
2|b|2
3|c|2
3|b|1
4|a|1
4|b|2
5|b|2
5|a|1
预期结果 输入:(c,a,b) 输出:1
输入:(c,a) 输出:NULL(无行)
输入:(c,b) 输出:2
输入:(a,b) 输出:4,5 - 单独的行
输入:(a,b,c) 输出:NULL(无行)
答案 0 :(得分:2)
您需要先将输入插入包含Rank
和StudentId
的表格。我想出了一种方法,你可以做到这一点,而无需解析csv。它使用输入中CHARINDEX
的{{1}}。请注意,如果您的输入值不在表中,则会被忽略。当然你可以解析csv而不是你。
在表中输入后,您需要做的就是将输入加入到表中以仅获取与输入匹配的记录。然后StudentId
并获取与您输入中的记录具有相同计数的GROUP BY SubjectId
,并将与您表格中SubjectId
的记录相同的计数。
所有答案都是这样的。 (出于某种原因SubjectId
无法保存,所以我做了(*)
)。
(* )
答案 1 :(得分:1)
由于我对@ fqhv的答案的编辑遭到拒绝,我在借用他的时候扩展了我之前的答案:
DECLARE @CommaSeparatedStudentIds varchar(max) = 'c,a';
DECLARE @InputTable AS TABLE (
[Rank] INT IDENTITY(1,1),
StudentId VARCHAR(25) --make this match your StudentID field
)
INSERT INTO @InputTable (StudentId)
SELECT value from STRING_SPLIT(@CommaSeparatedStudentIds,',')
/* If STRING_SPLIT isn't available, you can do this other ways (see after code) */
Select
t.SubjectId
from
MyTable t
FULL OUTER JOIN @InputTable i ON
t.StudentId = i.StudentId AND
t.Rank = i.Rank
group by
t.SubjectId
having
count(*) = sum(case when t.Rank = i.Rank then 1 else 0 end)
有关STRING_SPLIT
的替代方案,请参阅此帖子:
Split function equivalent in T-SQL?
如果我们在MySQL中,您在评论中添加的修改版本可以很好地运行:
set @CommaSeparatedStudentIds = 'a,b';
SELECT
t.SubjectId
FROM
MyTable t
group by t.SubjectId
HAVING GROUP_CONCAT(t.StudentId order by t.Rank SEPARATOR ',') = @CommaSeparatedStudentIds