【问题标题】:Creating my custom view in SQL在 SQL 中创建我的自定义视图
【发布时间】:2017-11-30 16:07:04
【问题描述】:

我有一张这样的桌子:

  • UserName nvarchar(50)(主键)
  • FieldId nvarchar(50)(主键)
  • AvgScore float

如果我想创建一个显示“每个 UserName 的最大 AvgScore 是多少”的视图,可以按如下方式轻松创建:

SELECT  
    UserName, MAX(AvgScore) AS MaxAvgScore
FROM
    dbo.tblUsersFields
GROUP BY 
    UserName

但我想确定与MaxAvgScore 相关的FieldId。我试过了:

SELECT  
    UserName, FieldId, MAX(AvgScore) AS MaxAvgScore
FROM    
    dbo.tblUsersFields
GROUP BY 
    UserName

但这不起作用。这会导致错误:

选择列表中的“FieldId”列无效,因为它既不包含在聚合函数中,也不包含在 GROUP BY 子句中。

我能做什么?

【问题讨论】:

  • 添加一些示例表数据和预期的结果。
  • 一般 GROUP BY 规则说:如果指定了 GROUP BY 子句,则 SELECT 列表中的每个列引用必须标识一个分组列或作为集合函数的参数。即尝试GROUP BY UserName, FieldId
  • 您要么必须聚合FieldID 列(sum / avg / max / 等),要么将其添加到group by 子句(...group by UserName, FieldID
  • 嗨。谢谢您的回复。在我的表中,每个UserName 可以有多个FieldId,如果我使用GROUP BY UserName, FieldId,则会显示UserNameFieldId 的所有组合,而我只想为每个UserName 指定一行指定相关@ 987654339@.
  • 您使用的是哪个DBMS 产品? “SQL”只是一种查询语言,不是特定数据库产品的名称。

标签: sql select group-by


【解决方案1】:

首先获取每个用户的 max(avgscore):

 SELECT username, max(avgscore) as maxavgscore) 
 FROM dbo.tblUserFields
 GROUP BY Username

现在我们可以将此结果集加入您的 tblUserfields 表中,以使用 INNER JOIN 获得与此唯一 Username, MaxAvgScore 组合相对应的 FieldID

SELECT t1.username, t2.FieldID, t1.maxavgscore
FROM
    (
        SELECT username, max(avgscore) as maxavgscore
         FROM dbo.tblUserFields
         GROUP BY Username
    ) t1
    INNER JOIN dbo.tblUserFields t2 ON
        t1.username = t2.username 
        AND t1.maxavgscore = t2.avgscore

【讨论】:

  • 感谢@JNevill。那太棒了。但是,如果两个分数满足表中的 MaxScore,则此命令会同时显示它们。这种情况我该怎么办?
  • 亲爱的@JNevill,如果我使用MIN(DISTINCT t2.FieldId) AS FieldId2 而不是t2.FieldId 并将GROUP BY t1.UserName, t1.MaxAvgScore 放在代码末尾,问题就解决了。非常感谢。
【解决方案2】:

您需要在GROUP BY 子句中指定所有非聚合函数列。

SELECT  UserName, FieldId, MAX(AvgScore) AS MaxAvgScore
FROM    dbo.tblUsersFields
GROUP BY UserName, FieldId

【讨论】:

  • 谢谢@Dessma。但是在我的表中,每个UserName 可以有几个FieldId,如果我使用GROUP BY UserName, FieldId,则会显示UserNameFieldId 的所有组合,而我只希望每个UserName 指定相关的一行FieldId.
【解决方案3】:

在 SQL 中,您只能对属于 GROUP BY 语句的列或作为聚合函数的参数的列进行寻址。

而不是

GROUP BY UserName

GROUP BY UserName, FieldId

如果您有相同用户名的备用字段 ID,您将需要类似以下内容:

SELECT t1.*, t2.FieldId FROM (
SELECT UserName, MAX(AvgScore) FROM tblUsersFields GROUP BY UserName) t1
LEFT JOIN tblUsersFields t2 ON t2.UserName = t1.UserName

这将为每个 FieldId 提供一行。

【讨论】:

  • 感谢@Olaf Watteroth。但是这段代码显示所有数据,如GROUP BY UserName, FieldId
【解决方案4】:

感谢@JNevill,我将他的答案改进为最终答案: (请参阅@JNevill 的回答和相关的 cmets。)

SELECT  t1.UserName, MIN(DISTINCT t2.FieldId) AS FieldId2, t1.MaxAvgScore
FROM
(SELECT  UserName, MAX(AvgScore) AS MaxAvgScore
 FROM    dbo.tblUsersFields
 GROUP BY UserName) AS t1
 INNER JOIN dbo.tblUsersFields AS t2 ON
 t1.UserName = t2.UserName AND t1.MaxAvgScore = t2.AvgScore
 GROUP BY t1.UserName, t1.MaxAvgScore

【讨论】:

    猜你喜欢
    • 2017-12-04
    • 1970-01-01
    • 1970-01-01
    • 2011-05-24
    • 2015-06-12
    • 2015-08-17
    • 2016-04-30
    相关资源
    最近更新 更多