【问题标题】:Adding a join to a count() query向 count() 查询添加连接
【发布时间】:2011-03-14 08:45:10
【问题描述】:

下面的代码取自我之前的问题here ,并做了一些改动。

SELECT *
FROM ES_TOOL
  INNER JOIN ES_HARDWARE ON ES_HARDWARE.eshw_ID = ES_TOOL.ESTOOL_HARDWARE 
  INNER JOIN ES_PAYMENT  on ES_payment.espay_id = es_TOOL.estool_payment 

  LEFT JOIN (
    SELECT
      tchap.estch_tool, tfacet.estfa_tool,
      count(marks.esmrk_value) AmtMarks 
    FROM ES_MARK marks 
      left Join ES_TOOL_FACET tfacet ON marks.esmark_tool_facet = tfacet.estfa_id --line added
      left Join ES_TOOL_CHAPTER tchap ON marks.esmark_tool_chapter = tchap.estch_id 
    GROUP BY tchap.estch_tool 
  ) h  ON ES_TOOL.estool_id = h.estch_tool

我正在尝试添加一个额外的连接,以尝试从满足任一左连接“ON”条件的“标记”中获取标记计数。如果没有额外的行,查询将执行,但不计算符合“方面”标准的标记。有了它,我收到以下错误:

消息 8120,第 16 级,状态 1,第 1 行

列 'ES_TOOL_FACET.estfa_tool' 在选择列表中无效,因为它既不包含在聚合函数或 GROUP BY 子句中。

任何帮助将不胜感激。

【问题讨论】:

  • 如果您可以在问题中包含一些示例输入和输出数据,则更容易具体说明答案。
  • tchap.estch_tooltfacet.estfa_tool 可以保持相同的值吗?如果可以,是否应该将相同值的匹配一起计算?

标签: sql sql-server join


【解决方案1】:

错误信息意味着 ES_TOOL_FACET.estfa_tool 需要包含在 Group By 中。

当您使用 Group By 时,所有非聚合列都必须包含在 group by 部分中。

【讨论】:

    【解决方案2】:

    这在你的内部查询中应该很明显:

    SELECT  tchap.estch_tool, tfacet.estfa_tool,  count(marks.esmrk_value) AmtMarks 
    FROM ES_MARK marks 
      left Join ES_TOOL_FACET tfacet ON marks.esmark_tool_facet = tfacet.estfa_id --line added
      left Join ES_TOOL_CHAPTER tchap ON marks.esmark_tool_chapter = tchap.estch_id 
    GROUP BY tchap.estch_tool 
    

    您有三个选定的列,estch_tool 位于 GROUP BY 子句中,esmrk_value 位于聚合函数中,estfa_tool 既不在 GROUP BY 子句中也不在聚合函数中。

    您的解决方案应该是:

    1. GROUP BY tchap.estch_tool, tfacet.estfa_tool
    2. AVG(tfacet.estfa_tool) 或任何聚合函数

    【讨论】:

    • 我试过: GROUP BY tchap.estch_tool, tfacet.estfa_tool ,但随后查询为每个工具返回 2 行与章节和方面匹配,而我需要为每个工具一个总计数章节和方面匹配。想法?
    • 那么,您必须调试您的查询。也许您在某个地方加入了一个将结果集扩展 2 的表(在这种情况下,您应该缺少 WHERE 子句)?啊,调试和调优 SQL 的乐趣……
    【解决方案3】:

    此查询存在语法错误 -

    SELECT  
                tchap.estch_tool, 
                tfacet.estfa_tool,  
                count(marks.esmrk_value) AmtMarks 
            FROM ES_MARK marks   
                left Join ES_TOOL_FACET tfacet ON 
                    marks.esmark_tool_facet = tfacet.estfa_id --line added  
                left Join ES_TOOL_CHAPTER tchap ON 
                    marks.esmark_tool_chapter = tchap.estch_id  
            GROUP BY tchap.estch_tool  
    

    GROUP BY 要求出现在 SELECT 列表中的任何列都应该被聚合或出现在 GROUP BY 子句中。

    所以在 tfacet.estfa_tool 上放置一个聚合函数 - MIN、MAX、SUM、AVG 等,因为它不会出现在 group by 子句中或包含在其中。

    【讨论】:

    • 哦,我的……我打字太慢了……已经有两个答案了!!
    【解决方案4】:

    我的解决方案有两种变体。哪一种更适合您可能取决于在对您的数据进行尝试时,哪一种会产生更好的执行计划。

    变体 #1 的描述:(在这两种情况下,我只描述主 SELECT 的 LEFT JOIN 子选择背后的逻辑,即实际被替换的部分。但脚本是完整的查询,相当于你的):

    1. 从两个 tools 表中提取并合并所有项目。
    2. 根据marks 表相应地加入列表。
    3. 按工具项对结果集进行分组并获取计数。

    查询:

    SELECT *
    FROM ES_TOOL
      INNER JOIN ES_HARDWARE ON ES_HARDWARE.eshw_ID = ES_TOOL.ESTOOL_HARDWARE 
      INNER JOIN ES_PAYMENT  on ES_payment.espay_id = es_TOOL.estool_payment 
    
      LEFT JOIN (
        SELECT
          tools.tool,
          COUNT(*) AS AmtMarks
        FROM (
          SELECT 'tchap'  AS tbl, estch_id AS id, estch_tool AS tool
          FROM ES_TOOL_CHAPTER
    
          UNION ALL
    
          SELECT 'tfacet' AS tbl, estfa_id AS id, estfa_tool AS tool
          FROM ES_TOOL_FACET
        ) tools
          INNER JOIN ES_MARK marks
            ON tools.tbl = 'tchap'  AND tools.id = marks.esmark_tool_chapter
            OR tools.tbl = 'tfacet' AND tools.id = marks.esmark_tool_facet
        GROUP BY tools.tool
      ) h ON ES_TOOL.estool_id = h.tool
    

    变体 #2

    1. 加入 ES_TOOL_CHAPTERmarks 并获取所有 estch_tool 值,包括重复值。
    2. 同样,加入 ES_TOOL_FACETmarks 并获取所有 estfa_tool 值,包括重复值。
    3. UNION ALL 两个集合。
    4. 按工具项对结果集进行分组并获取计数。

    还有查询:

    SELECT *
    FROM ES_TOOL
      INNER JOIN ES_HARDWARE ON ES_HARDWARE.eshw_ID = ES_TOOL.ESTOOL_HARDWARE 
      INNER JOIN ES_PAYMENT  on ES_payment.espay_id = es_TOOL.estool_payment 
    
      LEFT JOIN (
        SELECT
          tools.tool,
          COUNT(*) AS AmtMarks
        FROM (
          SELECT estch_tool AS tool
          FROM ES_TOOL_CHAPTER tools
            INNER JOIN ES_MARK marks ON tools.estch_id = marks.esmark_tool_chapter
    
          UNION ALL
    
          SELECT estfa_tool AS tool
          FROM ES_TOOL_FACET tools
            INNER JOIN ES_MARK marks ON tools.estfa_id = marks.esmark_tool_facet
        ) tools
        GROUP BY tools.tool
      ) h ON ES_TOOL.estool_id = h.tool
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-19
      • 2014-12-31
      • 1970-01-01
      • 2016-04-17
      • 2021-11-30
      • 2019-07-26
      相关资源
      最近更新 更多