【问题标题】:How can I get a count from a table joined to a Left Outer Join?如何从连接到左外连接的表中获取计数?
【发布时间】:2015-02-08 07:42:09
【问题描述】:

我有三张桌子。测试表 (AdminTest)、属于用户的测试表 (UserTest) 和属于每个用户测试的问题表 (UserTestQuestion):

管理测试

CREATE TABLE [dbo].[AdminTest] (
    [AdminTestId]  INT            IDENTITY (1, 1) NOT NULL,
    [Title]        NVARCHAR (100) NOT NULL
    CONSTRAINT [PK_AdminTest] PRIMARY KEY CLUSTERED ([AdminTestId] ASC));

用户测试

CREATE TABLE [dbo].[UserTest] (
    [UserTestId]    INT      IDENTITY (1, 1) NOT NULL,
    [AdminTestId]   INT      NOT NULL,
    [UserId]        INT      NOT NULL
    CONSTRAINT [PK_UT] PRIMARY KEY CLUSTERED ([UserTestId] ASC));

用户测试问题

CREATE TABLE [dbo].[UserTestQuestion] (
    [UserTestQuestionId]  INT              IDENTITY (1, 1) NOT NULL,
    [UserTestId]          INT              NOT NULL,
    [Answered]            BIT              DEFAULT ((0)) NOT NULL
    CONSTRAINT [PK_UQ] PRIMARY KEY CLUSTERED ([UserTestQuestionId] ASC)
);
  • AdminTest 可能有也可能没有 UserTest
  • UserTest 总是有 UserTestQuestions

我创建了这个 SQL 来从 AdminTest 和 UserTest 获取数据:

SELECT  userTest.StartedDate,
        temp.AdminTestId 
        -- AnsweredCount
        -- I want to get a count of the number of rows
        -- from the table UserTestQuestions that have
        -- the column 'Answered' set to 1 here.             
FROM
( SELECT AdminTest.AdminTestId
  FROM   AdminTest  
  JOIN   AdminTestQuestion ON  AdminTest.AdminTestId = AdminTestQuestion.AdminTestId     
GROUP BY 
  AdminTest.AdminTestId
) temp
LEFT OUTER JOIN UserTest ON  temp.AdminTestId = UserTest.AdminTestId
-- I want the above join to only join those UserTest tables that 
-- have a value of UserId set to for example 25

但现在我被困住了,有两件事我需要帮助。

  • 我需要能够仅显示属于给定 UserId 的 UserTests
  • 我需要报告 UserTests 中 Answered 设置为 1 的行数。

有人可以就如何将此功能添加到我的 SQL 中给我建议吗?

这是我需要的示例:

AdminTestId   UserTestStartedData  AnsweredCount

1             1/1/2001             25
2             2/2/2002             10
3                
4             4/4/2004             10

【问题讨论】:

    标签: sql sql-server join outer-join


    【解决方案1】:

    加入UserTestQuestion表并使用Conditional Aggregate仅在answered = 1时计数

    SELECT userTest.StartedDate,
           temp.AdminTestId,
           Count(CASE
                   WHEN UT.answered = 1 THEN 1
                 END) cnt
    FROM   (SELECT AdminTest.AdminTestId
            FROM   AdminTest
                   JOIN AdminTestQuestion
                     ON AdminTest.AdminTestId = AdminTestQuestion.AdminTestId
            GROUP  BY AdminTest.AdminTestId) temp
           INNER JOIN UserTest
                        ON temp.AdminTestId = UserTest.AdminTestId
           INNER JOIN [UserTestQuestion] UT
                   ON UserTest.UserTestId = UT.UserTest 
           Where  UserTest.UserTestId = 25
    

    另外,如果你想加入只加入那些UserTest 表 有 UserId=25 的值,那么 left join 将被转换为 Inner join

    更新:

    SELECT A.StartedDate,
           temp.AdminTestId,
           Count(CASE
                   WHEN A.answered = 1 THEN 1
                 END) cnt
    FROM   (SELECT AdminTest.AdminTestId
            FROM   AdminTest
                   JOIN AdminTestQuestion
                     ON AdminTest.AdminTestId = AdminTestQuestion.AdminTestId
            GROUP  BY AdminTest.AdminTestId) temp
           LEFT OUTER JOIN (SELECT userTest.StartedDate,
                                   UT.answered,
                                   UserTest.AdminTestId
                            FROM   UserTest
                                   INNER JOIN [UserTestQuestion] UT
                                           ON UserTest.UserTestId = UT.UserTest
                            WHERE  UserTest.UserTestId = 25) A
                        ON temp.AdminTestId = A.AdminTestId 
    Group by A.StartedDate,temp.AdminTestId
    

    【讨论】:

    • 非常感谢。我现在就试试这个。
    • 我想显示所有 AdminTest 表以及存在的那些 userTest 表(具有相同的 AdminTestId)并且 UserId = 25。有没有办法可以离开 LEFT OUTER JOIN 以及添加 WHERE 以将 UserTest 表限制为具有 25 个用户 ID 的表?
    • 我想我仍然需要 LEFT OUTER JOIN,因为即使没有用户表,我也想显示 Admin 表的列表。我刚刚在问题中添加了我需要的输出示例。我希望它能让它更清楚一点。
    • 我认为您的最新更新接近我的需要,但我仍然收到错误消息。我拿了你给我的代码,运行它,我已经将代码和错误消息添加到问题中,这样你就可以看到消息是什么。我在底部附近进行了一些小更改(UserTest > UserTestId),我还将 WHERE 中的检查设置为 1 =1,以便我可以轻松测试它。希望您对错误消息有一些想法。你认为 Answered = 1 的问题计数应该在最后一个 SELECT 中进行,即距离代码末尾 8 行?
    • 非常感谢。这现在有效!只是一个小问题。我看到您正在计算最外层选择中的 WHEN A.answered。您认为如果在以“LEFT OUTER JOIN (SELECT userTest.StartedDate,”开头的最内层选择中完成此操作会更有效吗?
    猜你喜欢
    • 1970-01-01
    • 2014-02-24
    • 1970-01-01
    • 1970-01-01
    • 2010-10-21
    • 2016-11-23
    • 2011-10-01
    • 2017-10-01
    • 2014-12-07
    相关资源
    最近更新 更多