【问题标题】:SQL Server: aggregate error on groupingSQL Server:分组聚合错误
【发布时间】:2018-07-23 15:31:32
【问题描述】:

我有一个名为 tasks 的表,其中列出了工作人员可以完成的不同任务。然后我有一个关系表,将已完成的任务链接到工作人员。 我正在尝试编写根据工作人员 ID 将任务分组到列表中的查询,但该查询给了我以下错误(见下文)。

Column 'mater.dbo.worker_task_completion.FK_task_id' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

表格

CREATE TABLE [dbo].[tasks]
(
    [task_id] [int] IDENTITY(1,1) NOT NULL,
    [name] [nvarchar](50) NOT NULL,
    [icon] [nvarchar](max) NULL,
    [isActive] [int] NOT NULL,
    [time] [int] NOT NULL,
    CONSTRAINT [PK_tasks] PRIMARY KEY CLUSTERED 
(
    [task_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]



CREATE TABLE [dbo].[worker_task_completion]
(
    [FK_worker_id] [int] NOT NULL,
    [FK_task_id] [int] NOT NULL,
    [update_date] [datetime] NOT NULL,
    CONSTRAINT [PK_worker_task_completion] PRIMARY KEY CLUSTERED 
(
    [FK_worker_id] ASC,
    [FK_task_id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

查询

SELECT top 100 wtc.FK_worker_id, 
                tasks = Stuff((SELECT ', ' + dbo.tasks.NAME 
                                FROM   dbo.tasks
                               WHERE  dbo.tasks.task_id = 
                                     wtc.FK_task_id
                               FOR xml path ('')), 1, 1, '')
        FROM   dbo.worker_task_completion AS wtc 
                LEFT JOIN dbo.tasks AS tc 
                       ON tc.task_id = wtc.fk_task_id
        -- WHERE  wtc.FK_worker_id IN ()
GROUP  BY wtc.FK_worker_id

【问题讨论】:

  • 错误不明白怎么办?问题出在哪里已经很清楚了。
  • 您的 SELECT 语句使用哪些聚合函数?
  • 你为什么使用GROUP BY而不使用任何聚合函数?
  • 我不是在 dbo.tasks.NAME 列上用东西聚合吗?
  • 不,你不是。 STUFF/FOR XML PATH 有助于聚合,但它们不是聚合。您使用的是什么版本的 SQL Server?

标签: sql sql-server group-by


【解决方案1】:

嗯。您不能将非聚合列用于相关子句。解决方法是将JOIN 移到子查询中:

SELECT top 100 wtc.FK_worker_id, 
       stuff((SELECT ', ' + t.NAME 
              FROM dbo.worker_task_completion wtc2 JOIN
                   dbo.tasks t
                   ON t.task_id = wtc2.FK_task_id
              WHERE wtc2.FK_worker_id = wtc.FK_worker_id
              FOR xml path ('')
             ), 1, 2, ''
            ) as tasks
FROM (SELECT DISTINCT wtc.FK_worker_id
      FROM dbo.worker_task_completion wtc 
     ) wtc
        -- WHERE  wtc.FK_worker_id IN ()

请注意,我更改了STUFF() 的第二个参数。大概,您想删除空格和逗号。

【讨论】:

    【解决方案2】:
    ;WITH CTE_worker_task_completion
     AS (SELECT [FK_worker_id]
               ,[FK_task_id]
         FROM [dbo].[worker_task_completion])
    
     ------------------------------------------
     SELECT [WT].[FK_worker_id]
           ,[Task]=Stuff(
            (
            SELECT ', '+[T].[Name]   
            FROM [dbo].[tasks] AS [T]
            INNER JOIN CTE_worker_task_completion AS [WTC]
                  ON [T].[Task_ID]=[WTC].[Task_ID]
          Where [WT].[Worker_ID]=[WTC].[Worker_ID]
            ORDER BY [T].[Name] FOR XML PATH('')
            ),1,1,'')
     FROM CTE_worker_task_completion AS [WT]
     GROUP BY [WT].[FK_worker_id];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-23
      • 1970-01-01
      • 2012-09-09
      • 1970-01-01
      • 2021-12-02
      • 1970-01-01
      • 2010-09-26
      相关资源
      最近更新 更多