Sql server sql联接,包括空记录和不存在的记录

Sql server sql联接,包括空记录和不存在的记录,sql-server,join,Sql Server,Join,我有以下表格。我正在尝试连接这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 or

我有以下表格。我正在尝试连接这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') 

用户表必须是当前定义的“左”表。你可能会陷入关于左连接和右连接的争论中,但从可读性和个人偏好来看,左连接才是正确的选择

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

用户表必须是当前定义的“左”表。你可能会陷入关于左连接和右连接的争论中,但从可读性和个人偏好来看,左连接才是正确的选择

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

您需要
用户
问题
的所有组合,即使是用户没有回答的问题。这类问题有些复杂,但并不少见

解决方法是首先在
问题
用户
之间创建笛卡尔积(
交叉连接
),然后才
左连接到
答案

因此,查询将是:

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
然后通过(用户)获得上述(问题)的所有组合

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

然后,完整查询变为:

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 ;

您需要
用户
问题
的所有组合,即使是用户没有回答的问题。这类问题有些复杂,但并不少见

解决方法是首先在
问题
用户
之间创建笛卡尔积(
交叉连接
),然后才
左连接到
答案

因此,查询将是:

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
然后通过(用户)获得上述(问题)的所有组合

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

然后,完整查询变为:

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 ;
我需要知道未回答的问题,以及未回答任何问题的用户

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

未回答的问题是在
tbl\u答案中没有匹配项的问题。这意味着
tbl_答案
反加入
tbl_问题

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\u答案中没有匹配项的用户。所以,这一个也有一个反连接:

SELECT
  u.firstName,
  u.lastName
FROM
  tbl_users AS u
WHERE NOT EXISTS (
  SELECT *
  FROM tbl_answers AS a
  WHERE u.userID = a.userID
);
我需要知道未回答的问题,以及未回答任何问题的用户

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

未回答的问题是在
tbl\u答案中没有匹配项的问题。这意味着
tbl_答案
反加入
tbl_问题

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\u答案中没有匹配项的用户。所以,这一个也有一个反连接:

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

谢谢你,奥利弗。答案表有一个用户ID。我会试试你的查询。奥利弗,这给了我10个结果。Daniela Pestova没有回答任何问题,所以我应该给她7个零分。共有7个问题分为两类。尽管如此,我必须说,用另一个查询左连接给了我一些想法。你没有一种方法将用户链接到问题,这就是为什么我建议添加一个调查表。除非你假设所有的用户都被问到了所有的问题,我觉得这些问题不对。您甚至可以在其中输入日期,以区分用户是否在多个场合回答了调查,您还可以使用它指定询问的问题,例如,如果您在调查中添加或删除问题。谢谢Oliver。答案表有一个用户ID。我会试试你的查询。奥利弗,这给了我10个结果。Daniela Pestova没有回答任何问题,所以我应该给她7个零分。共有7个问题分为两类。尽管如此,我必须说,用另一个查询左连接给了我一些想法。你没有一种方法将用户链接到问题,这就是为什么我建议添加一个调查表。除非你假设所有的用户都被问到了所有的问题,我觉得这些问题不对。您甚至可以在其中输入一个日期,以区分用户是否在多个场合回答了调查,您可以使用该日期指定询问了哪些问题,例如,如果您在调查中添加或删除了问题。是否希望列出所有用户/问题组合,即使他们没有回答?如果你包含了最终的期望结果,你会更容易理解你想要什么。你想要一个所有用户/问题组合的列表,即使他们没有回答?如果你包含了一个最终想要的结果,你就更容易理解你想要什么。你就是那个人!看起来像是爱琴海另一边的邻居。:)做得很好!!!你就是那个人!看起来像是爱琴海另一边的邻居。:)做得很好!!!