【问题标题】:Grouping by all non-aggregated columns in MSSQL按 MSSQL 中的所有非聚合列分组
【发布时间】:2016-07-28 07:57:36
【问题描述】:

假设我有两个表POPO_Line,我想列出PO 中的所有字段加上PO_Line 中链接回PO 中每一行的行数我会写一个查询像 -

SELECT
  PO.propA,
  PO.propB,
  PO.propC,
  PO.propD,
  PO.propE,
  ...
  PO.propY,
  COUNT(PO_Line.propA) LINES
FROM
  PO
LEFT JOIN
  PO_Lines
ON
  PO.ID = PO_Lines.PO_ID

显然,这会产生类似于 -

的错误

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

为了让查询运行,我将在查询末尾添加一个GROUP BY 子句,然后复制并粘贴我的选择行,就像这样 -

SELECT
  PO.propA,
  PO.propB,
  PO.propC,
  PO.propD,
  PO.propE,
  ...
  PO.propY,
  COUNT(PO_Line.propA) LINES
FROM
  PO
LEFT JOIN
  PO_Lines
ON
  PO.ID = PO_Lines.PO_ID
GROUP BY
  PO.propA,
  PO.propB,
  PO.propC,
  PO.propD,
  PO.propE,
  ...
  PO.propY

效果很好,但是感觉有点笨拙,尤其是如果我将列命名为 -

SELECT
  PO.propA AS 'FIRST PROPERTY',
  PO.propB AS 'SECOND PROPERTY',
  PO.propC AS 'THIRD PROPERTY',
  PO.propD AS 'ANOTHER PROPERTY',
  PO.propE AS 'YOU GET THE IDEA',
  ...
  PO.propY

我必须复制/粘贴 select 子句中的条目,然后删除列名。

所以我的问题是 - 是否有一种简写方法可以按 select 子句中找到的所有非聚合条目分组?

【问题讨论】:

  • 您可以只对聚合列和非聚合键字段执行 SELECT,然后加入到其余非聚合字段的另一个 SELECT DISTINCT。这也很笨拙,但它的优点是允许您执行 SELECT *,而不是显式列出所有非聚合字段。

标签: sql sql-server sql-server-2008 tsql


【解决方案1】:

我认为你只需要窗口函数:

SELECT . . .,
       COUNT(PO_Line.propA) OVER (PARTITION BY PO.ID) as LINES
FROM PO LEFT JOIN
     PO_Lines
     ON PO.ID = PO_Lines.PO_ID;

【讨论】:

  • 假设选择只从PO获取列,这可能会返回很多重复的行。
【解决方案2】:

我必须复制/粘贴 select 子句中的条目,然后删除列名。

我强烈建议使用block/column selection.Move , 作为第一个元素并对齐你的别名:

SELECT
   PO.propA AS 'FIRST PROPERTY'
  ,PO.propB AS 'SECOND PROPERTY'
  ,PO.propC AS 'THIRD PROPERTY'
  ,PO.propD AS 'ANOTHER PROPERTY'
  ,PO.propE AS 'YOU GET THE IDEA'
  ...
  ,PO.propY
  ,COUNT(PO_Line.propA) LINES
FROM  PO
LEFT JOIN  PO_Lines
  ON  PO.ID = PO_Lines.PO_ID
GROUP BY
   ...

SQL Server Management Studio 中使用简单的块选择SHIFT + ALT 突出显示并粘贴。

如果你使用其他编辑器找到对应的快捷键here

一次进行多次编辑很不错,比如添加架构、别名……等等。

【讨论】:

  • 大多数中途编辑器(至少在 Windows 上)使用 Alt 进行块选择;这甚至适用于 MS Word! ;)
  • 仍然有点尴尬,因为您需要格式化 SELECT 子句,以便当您有不同长度名称的字段时,他们都需要排队但说我学到了新东西!
  • @JohnC 这就是为什么你应该使用像 RedgateApex 这样的工具来为你做这件事。
【解决方案3】:

阅读您的查询,我认为您可能不需要GROUP BY 开头:

SELECT
  PO.propA,
  PO.propB,
  PO.propC,
  PO.propD,
  PO.propE,
  ...
  PO.propY,
  (SELECT COUNT(*) FROM PO_Lines WHERE PO.ID = PO_Lines.PO_ID) LINES
FROM
  PO

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-03
    • 2014-05-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多