【问题标题】:sql join including null and non existing recordssql join 包括空和不存在的记录
【发布时间】:2014-07-31 15:00:42
【问题描述】:

我有以下表格。我正在尝试加入这 4 个表,它会列出所有问题,即使用户没有回答用户和类别的任何问题。 有什么帮助吗?

select * 
from  tbl_category  c
inner join  tbl_questions  q on q.categoryID = c.categoryID
left join  tbl_answers  a on a.questionID = q.questionID
left join  tbl_users  u on u.userID = a.userID
order by u.userID

这只会给出 9 条记录。我需要知道未回答的问题,以及未回答任何问题的用户。

CREATE TABLE [dbo].[tbl_users](
    [userID] [int] IDENTITY(1,1) NOT NULL,
    [firstName] [varchar](50) NULL,
    [lastName] [varchar](50) NULL
) 
GO

CREATE TABLE [dbo].[tbl_questions](
    [questionID] [int] IDENTITY(1,1) NOT NULL,
    [categoryID] [int] NOT NULL,
    [description] [varchar](100) NULL
) 
GO

CREATE TABLE [dbo].[tbl_category](
    [categoryID] [int] IDENTITY(1,1) NOT NULL,
    [description] [varchar](50) NULL
) 
GO

CREATE TABLE [dbo].[tbl_answers](
    [answer_id] [int] IDENTITY(1,1) NOT NULL,
    [answerText] [varchar](250) NULL,
    [questionID] [int] NULL,
    [userID] [int] NULL
) 
GO

-- tbl_questions
insert into tbl_questions ( categoryID, description ) 
values ( 1, 'How do you balance life and work?') 

insert into tbl_questions ( categoryID, description ) 
values ( 1, 'Do you check voicemail and email when on vacation?') 

insert into tbl_questions ( categoryID, description ) 
values ( 1, 'What is your favorite book?') 

insert into tbl_questions ( categoryID, description ) 
values ( 2, 'What were your responsibilities?') 

insert into tbl_questions ( categoryID, description ) 
values ( 2, 'What is your greatest strength?') 

insert into tbl_questions ( categoryID, description ) 
values ( 2, 'What is your greatest weakness?') 

insert into tbl_questions ( categoryID, description ) 
values ( 2, 'How do you evaluate success?') 

-- tbl_users
insert into tbl_users ( firstName, lastName ) 
values ( 'Alessandra', 'Ambrosio' )

insert into tbl_users ( firstName, lastName ) 
values ( 'Adriana', 'Lima' )

insert into tbl_users ( firstName, lastName ) 
values ( 'Daniela', 'Pestova' )


-- tbl_answers
insert into tbl_answers ( answerText, questionID, userID ) 
values ( 'answer for q1', 1, 1) 

insert into tbl_answers ( answerText, questionID, userID ) 
values ( 'answer for q2', 2, 1) 

insert into tbl_answers ( answerText, questionID, userID ) 
values ( 'answer for q3', 3, 1) 

insert into tbl_answers ( answerText, questionID, userID ) 
values ( 'answer for q4', 4, 1) 

insert into tbl_answers ( answerText, questionID, userID ) 
values ( 'answer for q5', 5, 1) 

insert into tbl_answers ( answerText, questionID, userID ) 
values ( 'answer for q6', 6, 1) 

insert into tbl_answers ( answerText, questionID, userID ) 
values ( 'answer for q7', 7, 1) 

insert into tbl_answers ( answerText, questionID, userID ) 
values ( 'other answer for q5', 5, 2) 

insert into tbl_answers ( answerText, questionID, userID ) 
values ( 'other answer for q2', 2, 2) 

-- tbl_category
INSERT tbl_category (categoryID, description) VALUES (1, 'About You')
INSERT tbl_category (categoryID, description) VALUES (2, 'Job') 

【问题讨论】:

  • 您是否想要所有用户/问题组合的列表,即使他们没有回答?如果您包含最终所需的结果,则更容易理解您想要什么。

标签: sql-server join


【解决方案1】:

您需要usersquestions 的所有组合,即使对于用户没有回答的问题也是如此。这种问题有些复杂,但并不罕见。

解决它的方法是首先在 questionsusers 之间创建一个笛卡尔积 (CROSS JOIN) - 然后才将 LEFT JOINanswers

所以查询将是:

SELECT                           -- choose only the columns you want, not all (*)
    u.*, c.*, q.*, a.*     
FROM

问题与类别有关。我们希望:

    tbl_category AS c
  JOIN 
    tbl_questions AS q  ON  q.categoryID = c.categoryID

然后获取上述(问题)与(用户)的所有组合

  CROSS JOIN
    tbl_users AS u 

然后加入(答案)。请注意答案有 2 个连接条件,每个表(问题和用户)都有一个:

  LEFT JOIN
    tbl_answers AS a  ON  a.questionID = q.questionID
                      AND a.userID = u.userID

然后完整的查询变成:

SELECT  
    u.*, c.*, q.*, a.*     
FROM
    tbl_category AS c
  JOIN 
    tbl_questions AS q  ON  q.categoryID = c.categoryID
  CROSS JOIN
    tbl_users AS u 
  LEFT JOIN
    tbl_answers AS a  ON  a.questionID = q.questionID
                      AND a.userID = u.userID
ORDER BY
    u.userID ;

【讨论】:

  • 你这个男人!看起来像爱琴海另一边的邻居。 :) 做得很好!!!
【解决方案2】:

我需要知道未回答的问题,以及未回答任何问题的用户

您正在寻找两种不同的东西。这对我来说意味着您需要两个不同的查询。

未回答的问题是在tbl_answers 中没有匹配项的问题。这意味着tbl_answers 反加入到tbl_questions

SELECT
  Category = c.description,
  Question = q.description
FROM
  tbl_questions AS q
INNER JOIN
  tbl_category AS c ON q.categoryID = c.categoryID
WHERE NOT EXISTS (
  SELECT *
  FROM tbl_answers AS a
  WHERE q.questionID = a.questionID
);

没有回答任何问题的用户同样是在tbl_answers 中没有匹配项的用户。所以,这也是一个反加入:

SELECT
  u.firstName,
  u.lastName
FROM
  tbl_users AS u
WHERE NOT EXISTS (
  SELECT *
  FROM tbl_answers AS a
  WHERE u.userID = a.userID
);

【讨论】:

    【解决方案3】:

    用户表必须是当前定义的“左”表。您可能会就左连接和右连接争论不休,但从可读性和个人偏好来看,左连接是要走的路。

    select * 
    from tbl_users u 
    left join (select q.questionID,q.categoryID,q.description qdesc,
                    c.description catdesc,a.answer_id,a.answerText,a.userID
                from tbl_category  c
                inner join  tbl_questions  q on q.categoryID = c.categoryID
                left join  tbl_answers  a on a.questionID = q.questionID
                )qa on u.userid=qa.userid
    

    如果您需要为每个用户显示每个问题,我认为您将需要另一个将用户链接到问题的表格。有点像

    CREATE TABLE [dbo].[Survey](
        [surveyID] [int] IDENTITY(1,1) NOT NULL,
        [questionID] [int] IDENTITY(1,1) NOT NULL,
         [userID] [int] NULL
    

    【讨论】:

    • 谢谢奥利弗。答案表有一个用户 ID。我会试试你的查询。
    • 奥利弗,这给了我 10 个结果。 Daniela Pestova 没有回答任何问题,所以我应该给她 7 个空值。 2 类共 7 个问题。虽然,我必须说左连接与另一个查询给了我一些想法。
    • 您无法将用户与问题联系起来,这就是我建议添加调查表的原因。除非您假设所有用户都被问到所有我觉得不对劲的问题。您甚至可以在其中设置一个日期来区分用户是否多次回答了调查,并且您可以使用它来指定提出哪些问题,例如您是否在调查中添加或删除问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-03
    • 1970-01-01
    • 1970-01-01
    • 2014-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多