【问题标题】:How can SQL throw Column invalid because not in aggregate and not in GROUP BY when GROUP BY is not used anywhere当 GROUP BY 没有在任何地方使用时,SQL 如何抛出无效的列,因为不是在聚合中,也不是在 GROUP BY 中
【发布时间】:2022-06-28 00:51:25
【问题描述】:

在尝试使用 GpsGate 服务器的报告系统时,我尝试让我只获得每位用户一天的第一次和最后一次旅行。

系统太晦涩,无法获得任何帮助,但我偶然发现了一个我认为不可能的 SQL 错误,也许如果我明白我可以修复 SQL 的原因,那么报告?!

问题是我收到以下错误:

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

问题是:任何地方都没有GROUP BY

这个错误是怎么发生的?有没有其他不使用GROUP BY子句可以构成分组的东西?

整个 SQL 非常不可读,因为报告系统使用了许多子查询。

请不要真的试图理解整件事的作用,因为它读起来很可怕。我只需要一个提示,这里会发生任何分组:

SELECT
PeriodStart,
PeriodEnd,
ApplicationID,
SamplingStart AS StartTime,
SamplingEnd AS StopTime,
DistanceDetailed.Name
FROM
(
 SELECT
  CAST('2022-06-23T22:00:00' AS DATETIME) AS PeriodStart,
  CAST('2022-06-24T22:00:00' AS DATETIME) AS PeriodEnd,
  32 AS ApplicationID,
  Users.Username,
  Users.Name,
  DATEDIFF(
    SECOND,
    Distance01.SamplingStart,
    Distance01.SamplingEnd
  ) AS Duration,
      Distance01.SamplingStart,
      Distance01.SamplingEnd,
      Distance01.UserID,
      Distance01.StartAddress,
      Distance01.StopAddress,
      Distance01.DistanceGps,
      Distance01.DistanceOdo,
      Distance01.MaxSpeed,
      Distance01.AvgSpeed,
      Distance01.FatPointState,
      Distance01.Fuel
    FROM
    (
      SELECT
       data_time_stamp_start AS 'SamplingStart',
       data_time_stamp_end AS 'SamplingEnd',
       int_01 AS 'UserID',
       txt_01 AS 'StartAddress',
       txt_02 AS 'StopAddress',
       dbl_01 AS 'DistanceGps',
       dbl_02 AS 'DistanceOdo',
       dbl_03 AS 'MaxSpeed',
       dbl_04 AS 'AvgSpeed',
       dbl_05 AS 'Fuel',
       txt_03 AS 'FatPointState'
      FROM
      reportv3_data_store
      LEFT JOIN reportv3_data_store_ext01 ON reportv3_data_store.report_data_store_id = reportv3_data_store_ext01.report_data_store_id
     WHERE
      report_data_provider_id = 1
      AND int_01 IN (258, 259)
      AND application_id = 32
      AND data_time_stamp_start BETWEEN '2022-06-23T22:00:00'
      AND '2022-06-24T22:00:00'
      AND data_time_stamp_end BETWEEN '2022-06-23T22:00:00'
      AND DATEADD(DAY, 1, '2022-06-24T22:00:00')
      AND (
        true_break = 1
        OR (
          true_break = 0
          AND data_time_stamp_start != data_time_stamp_end
        )
      )
  ) AS Distance01
  JOIN (
    SELECT
      DISTINCT u.user_id AS UserID,
      u.username as Username,
      u.name as Name,
      u.description as Description,
      u.Surname as Surname,
      email as Email,
      driver_id as IButton
    FROM
      users u
      JOIN user_groups ug ON u.user_id = ug.user_id
      JOIN groups g ON g.group_id = ug.group_id
      AND g.application_id = 32
  ) AS Users ON Users.UserID = Distance01.UserID
WHERE
  Distance01.UserID IN (
    SELECT
      UserID
    FROM
      (
        SELECT
          tu.user_id AS UserID,
          t.tag_id AS TagID,
          t.tag_name AS Name,
          t.tag_description AS Description
        FROM
          tag t
          JOIN tag_users tu ON tu.tag_id = t.tag_id
        WHERE
          bo_type = 'Franson.Directory.UserTagWriter'
          AND t.application_id = 32
      ) AS TagUsers
    WHERE
      TagUsers.TagID IN (297)
  )
  AND Distance01.SamplingStart >= '2022-06-23T22:00:00'
  AND Distance01.SamplingEnd <= '2022-06-24T22:00:00'
  AND Distance01.FatPointState != 'sleep'
) AS DistanceDetailed
 JOIN (
  SELECT
    MIN(SamplingStart) AS StartOfDay,
    DistanceDetailed.UserID,
    DATEPART(DAY, DATEADD(SECOND, 7200, SamplingStart)) AS DayOfMonth
  FROM
  (
    SELECT
      CAST('2022-06-23T22:00:00' AS DATETIME) AS PeriodStart,
      CAST('2022-06-24T22:00:00' AS DATETIME) AS PeriodEnd,
      32 AS ApplicationID,
      Users.Username,
      Users.Name,
      DATEDIFF(
        SECOND,
        Distance01.SamplingStart,
        Distance01.SamplingEnd
      ) AS Duration,
      Distance01.SamplingStart,
      Distance01.SamplingEnd,
      Distance01.UserID,
      Distance01.StartAddress,
      Distance01.StopAddress,
      Distance01.DistanceGps,
      Distance01.DistanceOdo,
      Distance01.MaxSpeed,
      Distance01.AvgSpeed,
      Distance01.FatPointState,
      Distance01.Fuel
    FROM
      (
        SELECT
          data_time_stamp_start AS 'SamplingStart',
          data_time_stamp_end AS 'SamplingEnd',
          int_01 AS 'UserID',
          txt_01 AS 'StartAddress',
          txt_02 AS 'StopAddress',
          dbl_01 AS 'DistanceGps',
          dbl_02 AS 'DistanceOdo',
          dbl_03 AS 'MaxSpeed',
          dbl_04 AS 'AvgSpeed',
          dbl_05 AS 'Fuel',
          txt_03 AS 'FatPointState'
        FROM
          reportv3_data_store
          LEFT JOIN reportv3_data_store_ext01 ON reportv3_data_store.report_data_store_id = reportv3_data_store_ext01.report_data_store_id
        WHERE
          report_data_provider_id = 1
          AND int_01 IN (
            258,
            259
          )
          AND application_id = 32
          AND data_time_stamp_start BETWEEN '2022-06-23T22:00:00'
          AND '2022-06-24T22:00:00'
          AND data_time_stamp_end BETWEEN '2022-06-23T22:00:00'
          AND DATEADD(DAY, 1, '2022-06-24T22:00:00')
          AND (
            true_break = 1
            OR (
              true_break = 0
              AND data_time_stamp_start != data_time_stamp_end
            )
          )
      ) AS Distance01
      JOIN (
        SELECT
          DISTINCT u.user_id AS UserID,
          u.username as Username,
          u.name as Name,
          u.description as Description,
          u.Surname as Surname,
          email as Email,
          driver_id as IButton
        FROM
          users u
          JOIN user_groups ug ON u.user_id = ug.user_id
          JOIN groups g ON g.group_id = ug.group_id
          AND g.application_id = 32
      ) AS Users ON Users.UserID = Distance01.UserID
    WHERE
      Distance01.UserID IN (
        SELECT
          UserID
        FROM
          (
            SELECT
              tu.user_id AS UserID,
              t.tag_id AS TagID,
              t.tag_name AS Name,
              t.tag_description AS Description
            FROM
              tag t
              JOIN tag_users tu ON tu.tag_id = t.tag_id
            WHERE
              bo_type = 'Franson.Directory.UserTagWriter'
              AND t.application_id = 32
          ) AS TagUsers
        WHERE
          TagUsers.TagID IN (297)
      )
      AND Distance01.SamplingStart >= '2022-06-23T22:00:00'
      AND Distance01.SamplingEnd <= '2022-06-24T22:00:00'
      AND Distance01.FatPointState != 'sleep'
  ) AS DistanceDetailed
) AS StartTag ON StartTag.UserID = DistanceDetailed.UserID
 AND DistanceDetailed.FatPointState = 'run'
 AND DATEPART(DAY, DATEADD(SECOND, 7200, SamplingStart)) = DATEPART(DAY, DATEADD(SECOND, 7200, StartTag.StartOfDay))
JOIN (
 SELECT
  MAX(SamplingStart) AS EndOfDay,
  DistanceDetailed.UserID,
  DATEPART(DAY, DATEADD(SECOND, 7200, SamplingStart)) AS DayOfMonth
 FROM
  (
    SELECT
      CAST('2022-06-23T22:00:00' AS DATETIME) AS PeriodStart,
      CAST('2022-06-24T22:00:00' AS DATETIME) AS PeriodEnd,
      32 AS ApplicationID,
      Users.Username,
      Users.Name,
      DATEDIFF(
        SECOND,
        Distance01.SamplingStart,
        Distance01.SamplingEnd
      ) AS Duration,         
      Distance01.SamplingStart,
      Distance01.SamplingEnd,
      Distance01.UserID,
      Distance01.StartAddress,
      Distance01.StopAddress,
      Distance01.DistanceGps,
      Distance01.DistanceOdo,
      Distance01.MaxSpeed,
      Distance01.AvgSpeed,
      Distance01.FatPointState,
      Distance01.Fuel
    FROM
      (
        SELECT
          data_time_stamp_start AS 'SamplingStart',
          data_time_stamp_end AS 'SamplingEnd',
          int_01 AS 'UserID',
          txt_01 AS 'StartAddress',
          txt_02 AS 'StopAddress',
          dbl_01 AS 'DistanceGps',
          dbl_02 AS 'DistanceOdo',
          dbl_03 AS 'MaxSpeed',
          dbl_04 AS 'AvgSpeed',
          dbl_05 AS 'Fuel',
          txt_03 AS 'FatPointState'
        FROM
          reportv3_data_store
          LEFT JOIN reportv3_data_store_ext01 ON reportv3_data_store.report_data_store_id = reportv3_data_store_ext01.report_data_store_id
        WHERE
          report_data_provider_id = 1
          AND int_01 IN (
            258,
            259
          )
          AND application_id = 32
          AND data_time_stamp_start BETWEEN '2022-06-23T22:00:00'
          AND '2022-06-24T22:00:00'
          AND data_time_stamp_end BETWEEN '2022-06-23T22:00:00'
          AND DATEADD(DAY, 1, '2022-06-24T22:00:00')
          AND (
            true_break = 1
            OR (
              true_break = 0
              AND data_time_stamp_start != data_time_stamp_end
            )
          )
      ) AS Distance01
      JOIN (
        SELECT
          DISTINCT u.user_id AS UserID,
          u.username as Username,
          u.name as Name,
          u.description as Description,
          u.Surname as Surname,
          email as Email,
          driver_id as IButton
        FROM
          users u
          JOIN user_groups ug ON u.user_id = ug.user_id
          JOIN groups g ON g.group_id = ug.group_id
          AND g.application_id = 32
      ) AS Users ON Users.UserID = Distance01.UserID
    WHERE
      Distance01.UserID IN (
        SELECT
          UserID
        FROM
          (
            SELECT
              tu.user_id AS UserID,
              t.tag_id AS TagID,
              t.tag_name AS Name,
              t.tag_description AS Description
            FROM
              tag t
              JOIN tag_users tu ON tu.tag_id = t.tag_id
            WHERE
              bo_type = 'Franson.Directory.UserTagWriter'
              AND t.application_id = 32
          ) AS TagUsers
        WHERE
          TagUsers.TagID IN (297)
      )
      AND Distance01.SamplingStart >= '2022-06-23T22:00:00'
      AND Distance01.SamplingEnd <= '2022-06-24T22:00:00'
      AND Distance01.FatPointState != 'sleep'
  ) AS DistanceDetailed
) AS EndeTag ON EndeTag.UserID = DistanceDetailed.UserID
AND DistanceDetailed.FatPointState = 'run'
AND DATEPART(DAY, DATEADD(SECOND, 7200, SamplingStart)) = DATEPART(DAY, DATEADD(SECOND, 7200, EndeTag.EndOfDay))
ORDER BY
  DATEPART(DAY, DATEADD(SECOND, 7200, SamplingStart)),
  DistanceDetailed.UserID

【问题讨论】:

  • 因为你有非窗口聚合函数,并且在同一范围内有非聚合列,你必须有一个GROUP BY 子句。因此,您省略了 GROUP BY 是缺陷,或者您的其他列应该被聚合,因此您不需要 GROUP BY 子句..
  • 您的 MIN(SamplingStart) 没有分组依据。
  • MAX(SamplingStart) OVER (PARTITION BY DistanceDetails.UserID) AS EndOfDay??
  • 请注意,错误消息显示的是“要么...或”,而不是标题中的“和”。在没有group by 的情况下使用聚合函数意味着一种类似于group by 'All' -- *invalid sql 的逻辑分组。也就是说,它将所有行折叠成一行。

标签: sql-server group-by


【解决方案1】:

因为您有非窗口聚合函数,并且在同一范围内有非聚合列,所以您必须有一个 GROUP BY 子句。因此,您省略了 GROUP BY 是缺陷,或者您的其他列应该被聚合,因此您不需要 GROUP BY 子句。

例如这个查询

select max(OrderDate) OrderDate, SalesOrderID
from Sales.SalesOrderHeader

失败并出现同样的错误。显然,一些引擎允许这样做,并将其视为全局聚合,SQL Server 要求您将窗口聚合用于:

select max(OrderDate) over () OrderDate, SalesOrderID
from Sales.SalesOrderHeader

尝试使用报告系统时

所以这似乎是报告系统中的一个错误。

【讨论】:

    猜你喜欢
    • 2020-04-17
    • 1970-01-01
    • 1970-01-01
    • 2014-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多