根据返回多行的WHERE子句选择行

时间:2014-01-08 13:01:11

标签: sql sql-server subquery

 Mentor table
+--------------+
| id  |  name  |
+-----+--------+
|  1  | name1  |
|  2  | name2  |
|  3  | name3  |
+-----+--------+

 MentorLanguage table
+------------------+
| id  |  language  |
+-----+------------+
|  1  |   english  |
|  1  |   french   |
|  1  |   german   |
|  2  |   chinese  |
|  2  |   english  |
|  3  |   russian  |
|  3  |   german   |
|  3  |   greek    |
+-----+------------+

 Student table
+--------------+
| id  |  name  |
+-----+--------+
|  A  | name1  |
|  B  | name2  |
|  C  | name3  |
+-----+--------+

 StudentLanguage table
+------------------+
| id  |  language  |
+-----+------------+
|  A  |   english  |
|  A  |   french   |
|  B  |   chinese  |
|  B  |   german   |
|  C  |   russian  |
|  C  |   spanish  |
|  C  |   greek    |
+-----+------------+


我想根据mentorstudentlanguage匹配,例如:

如果student A知道englishfrench,则他将与至少知道mentorsenglish的所有french匹配。< / p>

student A (english, french)
---------------------------------
mentor 1 (english, french, german); 
mentor 2 (chinese, english); 


我试过了

select * from Mentor m
where m.id =
( select ml.id from MentorLanguage ml, StudentLanguage sl
  where ml.language like sl.language 
  group by ml.id )

Subquery returned more than 1 value以来无效。

3 个答案:

答案 0 :(得分:0)

有很多方法可以做到这一点。我想这只取决于您在结果集中的偏好和/或需求。我已经包括两种方式来满足这个要求。很简单。如果您需要其他退回结果,请与我们联系。

CREATE TABLE #Mentor ([id] INT Identity, [name] NVARCHAR(20))
GO

INSERT INTO #Mentor(name)
VALUES ('John Smith'),('Jack Smith'),('Jane Smith')

CREATE TABLE #MentorLanguage ([id] INT, [language] NVARCHAR(20))
GO

INSERT INTO #MentorLanguage([id],[language])
VALUES (1,'English'),(1,'French'),(1,'German')
      ,(2,'Chinese'),(2,'English'),(3,'Russian')
      ,(3,'German'),(3,'Greek')

CREATE TABLE #Student([id] NVARCHAR(2), [name] NVARCHAR(20))
GO

INSERT INTO #Student ([id],[name])
VALUES ('A','name1'),('B','name2'),('C','name3')

CREATE TABLE #StudentLanguage ([id] NVARCHAR(2),[language] NVARCHAR(20))
GO

INSERT INTO #StudentLanguage ([id],[language])
VALUES ('A','English'),('A','French'),('B','Chinese'),('B','German'),('C','Greek')

/* Inner Join to between #MentorLanguage and #StudentLanguage 
    would elimate rows where the mentor and student don't match */
SELECT * 
FROM #Mentor m
INNER JOIN #MentorLanguage ml ON m.[id] = ml.id
INNER JOIN #StudentLanguage sl ON ml.[language] = sl.[language]
INNER JOIN #Student s ON s.id = sl.id

/* Agg Count of how many students each mentor could teach
   based on the languages students know */

SELECT m.name, count(s.id) as [count]
FROM #Mentor m
INNER JOIN #MentorLanguage ml ON m.[id] = ml.id
INNER JOIN #StudentLanguage sl ON ml.[language] = sl.[language]
INNER JOIN #Student s ON s.id = sl.id
GROUP BY m.name

答案 1 :(得分:0)

您可以尝试在where子句中使用“IN”运算符而不是=。这允许您执行“包含”而不是与单个值进行比较。

select * from Mentor m
where m.id IN
( select ml.id from MentorLanguage ml, StudentLanguage sl
  where ml.language like sl.language 
  group by ml.id )

答案 2 :(得分:0)

你有没有想到这个?

select 
Student.id StudentId,
group_concat(distinct StudentLanguage.language) Languages,
group_concat(distinct Mentor.id) MentorIds from 
Student join StudentLanguage on (Student.id = StudentLanguage.id) 
join MentorLanguage on (StudentLanguage.language = MentorLanguage.language) 
join Mentor on (MentorLanguage.id = Mentor.id) group by Student.id;

结果:

+-----------+----------------+-----------+
| StudentId | Languages      | MentorIds |
+-----------+----------------+-----------+
| A         | french,english | 1,2       |
| B         | german,chinese | 1,3,2     |
| C         | russian,greek  | 3         |
+-----------+----------------+-----------+

对于最后一行,C知道西班牙语,但没有导师知道。如果您还需要西班牙语,请使用左连接。