【问题标题】:JOIN for Membership table加入会员表
【发布时间】:2010-11-25 23:13:05
【问题描述】:

为什么微软只为一张表使用带有 GroupBy 子句的愚蠢示例?

http://msdn.microsoft.com/en-us/library/bb896341.aspx

为什么当我尝试选择一些不在 GroupBy 中的字段时会导致错误? 错误表示当前上下文中不存在 GroupBy 子句中不存在的字段。

using (Entities db = new Entities())
{
    var query = "SELECT RLS.RoleId, UIR.UserId, UIR.RoleId, USR.UserName FROM Entities.aspnet_Roles AS RLS " +
                 "INNER JOIN Entities.vw_aspnet_UsersInRoles AS UIR " +
                 "ON RLS.RoleId = UIR.RoleId " + 
                 "INNER JOIN Entities.aspnet_Users AS USR " + 
                 "ON UIR.UserId = USR.UserId " + 
                 //"GROUP BY RLS.RoleId"  // is uncomment - it says UserId doesn't exist in context
                 ;
    var x = new ObjectQuery<DbDataRecord>(query, db);
    var y = x.ToTraceString().Replace("\n", " ").Replace("\t", " ").Replace("\r", " ");
}

LINQ 也一样:

var x = from RLS in db.aspnet_Roles
                        join URS in db.vw_aspnet_UsersInRoles
                        on RLS.RoleId equals URS.RoleId
                        join USR in db.aspnet_Users
                        on URS.UserId equals USR.UserId
                        group RLS by RLS.RoleId into GRP
                        select new
                        {
                            GRP.Key
                        };

问题是:如何选择所有字段和GroupBy只选择一个字段?

提前致谢。

【问题讨论】:

  • 您能解释一下您希望如何选择所有字段并对记录进行分组吗?您是否正在寻找唯一的字段集,在这种情况下您正在寻找 DISTINCT,或者您是否希望将记录与具有相同 RoleId 的所有条目一起交付,在这种情况下您正在寻找 ORDERBY。
  • 当人们尝试映射成员表并通过 EF 模型对其进行查询时,我仍然感到惊讶 - 使用提供程序 API!
  • RPM1984:如果你这么聪明,在这种情况下你可以回答如何添加 OrderBy、Distinct 并选择 3 个角色中的所有用户 + 那些使用 Provider API 没有任何角色的用户?我的角色很少,用户也很少。一个用户可以出现在多个角色中。为了防止用户重复,我想按 RoleId 对选择结果进行分组。
  • Lazarus:你可能是对的,在我的情况下最好使用 DISTINCT。谢谢。
  • Lazarus:虽然没有,但实际上 DISTINCT 并没有帮助,因为这是一个 JOINed 结果,所以无论如何记录都会有所不同......所以这是 GROUP BY 的情况

标签: asp.net sql linq entity-framework


【解决方案1】:

所有不在GROUP BY 子句中的字段都必须是聚合表达式,例如AVG(...) 或SUM(...) 或MAX(...) 等。

所以这是错误的:

SELECT RLS.RoleId, UIR.UserId, UIR.RoleId, USR.UserName
(...)
GROUP BY RLS.RoleId

因为SELECT 中的最后三个表达式应该以某种方式聚合或添加到GROUP BY 子句中。

这是合乎逻辑的,因为通过指定 GROUP BY RLS.RoleId,您说 RLS.RoleId 在最终结果中应该是唯一的,因此每个值只有一行。但是对于每个 RLS.RoleID,UIR.UserId、UIR.RoleId 或 USR.UserName 可能有多个值。因此,您需要告诉 DBMS 如何将它们排成一行:平均值、最大值、最小值... > 的列值应该是唯一的。另见example。

【讨论】:

    【解决方案2】:

    我没有看到您发布的查询中使用了任何聚合函数(COUNT、SUM、AVG 等)。因此,没有必要包含 GROUP BY 表达式,也没有理由这样做。您能解释一下您要完成的工作吗?

    【讨论】:

    • 我的角色和用户很少。一个用户可以出现在多个角色中。为了防止用户重复,我想按 RoleId 对选择结果进行分组。
    • 好的,但是你想要哪个用户角色的结果?
    • 例如,如果这是一个“经理”,那么它应该包含三个角色的用户 - 经理、客户、用户以及“匿名”,即那些不属于这些角色的人(角色管理员也应该被排除)。所以条件应该是这样的 - WHERE RoleName IN (Manager, Customer, User) OR RoleName = NULL
    【解决方案3】:

    我想我没听懂littlegreen。 他的建议真的很有帮助......虽然我对 SQL Server 与 MySQL 相比感到不安(有足够的设置一个分组字段)。

    有效!

    SELECT DISTINCT 
       RLS.RoleId, 
       COUNT(RLS.RoleId) AS RID_CNT, 
       MAX(CAST(UIR.UserId AS VARCHAR(36))) AS EXPR1, 
       MAX(CAST(USR.UserName AS VARCHAR(36))) AS EXPR2
    FROM aspnet_Roles AS RLS 
    INNER JOIN vw_aspnet_UsersInRoles AS UIR ON RLS.RoleId = UIR.RoleId 
    INNER JOIN aspnet_Users AS USR ON UIR.UserId = USR.UserId
    GROUP BY RLS.RoleId
    

    【讨论】:

    • DISTINCT 在这种情况下不是必需的,因为您已经按 RoleID 分组。
    • 我很高兴这对你有用,但这真的是你想要的查询吗?现在它将显示每个角色的用户数量,以及该角色的字母数字最高的 UserID 和 UserName,它们不一定相同。例如。当您在 RoleID 'managers' 中有一个名为 Zacharias 的用户 81 和名为 Andrew 的用户 9 时,它将显示一行:Managers, 2, 9, Zacharias 在我看来这并没有真正用处.这真的是你想要展示的吗?
    • 在这种情况下,我只需将 UserId 添加到 GROUP BY 子句 - GROUP BY RLS.RoleId, USR.UserId
    猜你喜欢
    • 2020-03-18
    • 2021-06-06
    • 1970-01-01
    • 2021-06-27
    • 2020-09-27
    • 2018-12-03
    • 1970-01-01
    • 1970-01-01
    • 2011-09-27
    相关资源
    最近更新 更多