减法上的子查询和AVG()

时间:2011-06-20 10:27:13

标签: sql

处理查询以返回员工开始轮班然后到达第一个家的平均时间(此DB假定他们是推销员)。

我有什么:

SELECT l.OFFICE_NAME, crew.EMPLOYEE_NAME, //avg(first arrival time)
FROM LOCAL_OFFICE l, CREW_WORK_SCHEDULE crew,
WHERE l.LOCAL_OFFICE_ID = crew1.LOCAL_OFFICE_ID

你可以看到AVG()命令被注释掉了,因为我知道他们到达工作的时间,以及他们到达第一宫的时间,并且可以使用这个来找到值:

(SELECT MIN(c.ARRIVE)
 FROM ORDER_STATUS c
 WHERE c.USER_ID = crew.CREW_ID)
 -(SELECT START_TIME
 FROM CREW_SHIFT_CODES
 WHERE WORK_SHIFT_CODE = crew.WORK_SHIFT_CODE)

最好的方法是将上述内容放入AVG()括号吗?只是尝试学习创建查询的最佳方法。如果您想要更多关于任何表格的信息,请询问,但希望他们都被命名,以便您知道他们将返回什么。

2 个答案:

答案 0 :(得分:2)

不要想到子查询:它们通常很慢。实际上,它们是逐行(RBAR)操作而不是基于设置

  1. 将所有表格加在一起
  2. 我使用派生表来计算第一次到达时间
  3. 聚合
  4. 类似于

    SELECT
        l.OFFICE_NAME, crew.EMPLOYEE_NAME,
        AVG(os.minARRIVE - cs.START_TIME)
    FROM
        LOCAL_OFFICE l
        JOIN
        CREW_WORK_SCHEDULE crew On l.LOCAL_OFFICE_ID = crew1.LOCAL_OFFICE_ID
        JOIN
        CREW_SHIFT_CODES cs ON cs.WORK_SHIFT_CODE = crew.WORK_SHIFT_CODE
        JOIN
        (SELECT MIN(ARRIVE) AS minARRIVE, USER_ID
         FROM ORDER_STATUS
         GROUP BY USER_ID
        ) os ON oc.USER_ID = crew.CREW_ID
    GROUP B
        l.OFFICE_NAME, crew.EMPLOYEE_NAME
    

    由于minARRIVE分组,这可能无法提供正确的数据:ORDER_STATUS没有足够的信息来显示“哪一天”或“哪个班次”。它只是“始终为该用户首次到达”

    编辑:

    这将为您提供平均分钟

    您可以使用DATEADD将其添加回minARRIVE,或使用某些%60(modul0)和/ 60(整数除法)更改为hh:mm

    AVG(
        DATEDIFF(minute, os.minARRIVE, os.minARRIVE)
        )
    

答案 1 :(得分:2)

根据我的评论,您提供的示例只会将一条记录返回到AVG功能,因此不会做太多。

但是,如果子查询返回了多条记录,那么您将子查询放在AVG()中的建议就可以了......

SELECT
  AVG((SELECT MIN(sub.val) FROM sub WHERE sub.id = main.id GROUP BY sub.group))
FROM
  main
GROUP BY
  main.group

(平均一组最小值,因此需要两个GROUP BY级别。)


在许多情况下,这会提供良好的性能,并且可维护。但有时子查询会变大,最好使用内联视图重新格式化...

SELECT
  main.group,
  AVG(sub_query.val)
FROM
  main
INNER JOIN
(
  SELECT
    sub.id,
    sub.group,
    MIN(sub.val) AS val
  FROM
    sub
  GROUP BY
    sub.id
    sub.group
)
  AS sub_query
    ON sub_query.id = main.id
GROUP BY
  main.group

注意:虽然看起来好像内联视图会计算出不需要的值(因此效率低下),但大多数RDBMS会优化这一点,因此只有所需的记录才能获得进程。 (优化器知道外部查询如何使用内部查询,并相应地构建执行计划。)