【问题标题】:SQL: conditioning multiple rows on an inner joined tableSQL:在内部连接表上调节多行
【发布时间】:2012-04-07 15:36:33
【问题描述】:

我需要一些有关 SQL 语法的帮助。

假设我有一个成员表、一个问题表和一个答案表,这些表的基本内容如下:

成员表:

memberId: primary key

问题表:

questionId: primary key,
questionText:varchar

答案表:

answerId: primary key,
questionId: int (relating to the row of the question in the questions table)
memberId: int (relating to the row of the member in the members table)
answerValue:varchar

表格会有更多的列,但为了解决这个问题,这些应该就足够了。

现在,在某些情况下,我希望运行一个查询,该查询将返回一个不同的成员 ID 列表,其中成员对问题列表的回答与某个值匹配。

例如:

假设问题表(第 1 行)中有一个问题,问题文本为:“你喜欢猫还是狗?”:

    questionId              questionText
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
         1                   Do you like cats or dogs?

那么members表从id 1到10有10个成员,在answers表中有对应的答案:

 answerid               questionId              memberId               answerId
---------------------------------------------------------------------------------------
 1                        1                       1                     cats
 2                        1                       2                     both
 3                        1                       3                     cats
 4                        1                       4                     cats
 5                        1                       5                     cats
 6                        1                       6                     dogs
 7                        1                       7                     dogs
 8                        1                       8                     dogs
 9                        1                       9                     dogs
 10                       1                       10                    both

这样查询就很简单了,例如回答狗的人:

SELECT DISTINCT memberId FROM members INNER JOIN answers ON members.memberId = answers.answerId WHERE answers.questionId = 1 AND answers.answerValue = 'dogs'

这将返回:

    memberId
---------------
       6
       7
       8
       9

但是如果我要在问题表中添加另一个问题呢:

    questionId              questionText
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
         1                   Do you like cats or dogs?
         2                   What is your favourite color?

答案表更新如下:

 answerid               questionId              memberId               answerId
---------------------------------------------------------------------------------------
 1                        1                       1                     cats
 2                        1                       2                     both
 3                        1                       3                     cats
 4                        1                       4                     cats
 5                        1                       5                     cats
 6                        1                       6                     dogs
 7                        1                       7                     dogs
 8                        1                       8                     dogs
 9                        1                       9                     dogs
 10                       1                       10                    both
 11                       2                       1                     blue
 12                       2                       2                     red
 13                       2                       3                     green
 14                       2                       5                     green
 15                       2                       4                     black
 16                       2                       6                     violet
 17                       2                       7                     pink
 18                       2                       8                     green
 19                       2                       9                     red
 20                       2                       10                    yellow

如何查询多个问题?

我正在寻找的是一种集合语法,可用于查询已回答任意数量问题的特定答案的不同成员列表,例如:

对于喜欢 ((dogs AND red) OR (cats AND green)) 的成员的查询应该返回:

    memberId
-----------------
      9
      3
      5

答案可能有任意组合。它的本质是如何查询一个内连接表的多个值?

感谢任何人提供的任何帮助,如果有点混乱,请见谅。

【问题讨论】:

  • 这有点难以解释在现实世界中的实现,但我已经尝试过了,基本上我设计了一个电子邮件引擎,它接受一个条件列表,例如(动物 = 猫和颜色 = 绿色(当然非常简化))并通过生成 sql 查询来查询数据库中匹配这些条件的成员,然后将电子邮件发送到返回的 id。
  • 就给出的示例而言,我已经尝试 SELECT DISTINCT memberId FROM members INNER JOIN answers ON members.memberId = answers.answerId WHERE (((answers.questionId = 1 AND answers.answerValue = 'dogs' ) AND (answers.questionId = 2 AND answers.answerValue = 'red')) OR ((answers.questionId = 1 AND answers.answerValue = 'cats') AND (answers.questionId = 2 AND answers.answerValue = 'green' )))
  • 我看不出你在这里问什么。您在上面的评论中的加入查询甚至没有意义。为什么要加入 memberid=answerid?
  • 我至少努力为您构建一个 sqlfiddle。 sqlfiddle.com/#!3/ae8d3/1

标签: sql sql-server join conditional-statements


【解决方案1】:

您可以选择回答其中一个问题的个人 ID,如下所示:

select distinct memberId where answerId = 'dogs'
select distinct memberId where answerId = 'red'

然后将 ands 替换为内连接,如下所示:

select memberId from
(select distinct memberId where answerId = 'dogs') D
inner join
(select distinct memberId where answerId = 'red') R
on D.MemberId = R.memberId

并将 OR 替换为 UNION,如下所示:

select memberId from
(select distinct memberId where answerId = 'dogs') D
inner join
(select distinct memberId where answerId = 'red') R
on D.MemberId = R.memberId
union
select memberId from
(select distinct memberId where answerId = 'cats') D
inner join
(select distinct memberId where answerId = 'green') R
on D.MemberId = R.memberId

正如你所说,这正是“set sintax”:

Set: each indivdual select
Intersection of sets : inner join
Union of sets: union

如果您需要额外的条件,例如只检查答案 1 和 2,您可以使用具有常见条件的 CTE,例如“answerId in (1,2)”,以避免在每个选择中写入相同的条件,从而使 sintax更清晰。

你也可以使用这个sintax,它更类似于你原来的写法:

select memberId from members M
where 
 ( exists (select 1 from answers where answerId='dogs' and memberId=M.member Id)
   and exists (select 1 from answers where answerId='red' and memberId=M.member Id) )
  or 
 ( exists (select 1 from answers where answerId='cats' and memberId=M.member Id)
  and exists (select 1 from answers where answerId='green' and memberId=M.member Id) )
-- I select 1 instead of * or any column for performance reasons

为了便于理解,我省略了添加额外检查(answerId 等)的详细信息。

【讨论】:

  • 谢谢你,这个周末我会做很多代码重写:((我的 SQL 查询生成。)
【解决方案2】:
SELECT DISTINCT memberId 
FROM members
WHERE answers.questionId=1 AND answers.answerValue IN ('dogs','red')
UNION
SELECT DISTINCT memberId 
FROM members
WHERE answers.questionId=2 AND answers.answerValue IN ('cats,'green'); 

【讨论】:

  • 一行如何满足这样的条件:(answers.answerValue = 'dogs' AND answers.answerValue ='red')?
  • 除了我的第一条评论,您不需要链接成员表。您可以从 answers 表中获取 memberId。为什么要加入成员表?想想你的问题!
猜你喜欢
  • 1970-01-01
  • 2017-11-09
  • 1970-01-01
  • 1970-01-01
  • 2018-01-07
  • 1970-01-01
  • 2017-05-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多