见狗眼开 2022-03-17 16:28 采纳率: 75%
浏览 23
已结题

CASE 添加 max() 便会报错 能否优化?

问题相关代码,请勿粘贴截图 :

            SELECT
                U.USER_NAME,
                R.ID,
                R.SIGN_ADDRESS,
                R.CREATE_TIME,
            CASE
                    WHEN MIN(DATE_FORMAT( R.CREATE_TIME, '%H%i' ))  > 0830 THEN '迟到' 
                    WHEN MAX(DATE_FORMAT( R.CREATE_TIME, '%H%i' ))  < 1830 THEN '早退' 
                     ELSE '正常打卡' 
                        END 
                        FROM
                            T_REMOTE_SIGN_DETAILS R
                            LEFT JOIN T_USER U ON U.ID = R.USER_ID
                            LEFT JOIN T_SCHOOL S ON S.ID = U.SCHOOL_ID 
                        WHERE
                            DATE_FORMAT( R.CREATE_TIME, '%Y%M' ) = DATE_FORMAT( NOW(), '%Y%M' ) 
                            AND S.ID = '270000000109' 
运行结果及报错内容 : > 1140 - In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated column 'ykt_csp.U.user_name'; this is incompatible with sql_mode=only_full_group_by
尝试得其他解决办法 :
CASE
        
        WHEN DATE_FORMAT( R.CREATE_TIME, '%H%i' ) BETWEEN 0730 AND 0830 THEN '上班打卡' 
        WHEN DATE_FORMAT( R.CREATE_TIME, '%H%i' ) BETWEEN 1800 AND 2000 THEN '下班打卡' 
          ELSE '打卡异常' 
            END 

我想要达到的结果 : CASE 添加 max() 便会报错 能否优化?
  • 写回答

3条回答 默认 最新

  • DarkAthena ORACLE应用及数据库设计方案咨询师 2022-03-17 21:48
    关注

    建议先描述一下你的场景,你目前这个sql语法是有问题的,如果用max或者min这样的聚合函数,而且不开窗,而且有分组字段,那么必须要使用group by .
    而且就算你这个sql能跑出数据,应该也不是你想要的数据,所以问题点并不在于case when和聚合函数一起用是否会报错,而是应该选择何种方式来实现你需要的场景。
    我先猜一下你的需求,你这个数据应该是个考勤打卡的流水记录,先暂时不管是否存在短时间内多次打卡的情况,以及是否有漏打卡的情况,即肯定有一条上班有一条下班,根据你sql的意思,应该是想保留当前查询的所有行,然后加一个字段识别这个人这一天是否存在迟到或者早退的情况,但这个判断的依据又不仅仅只是看本行数据,需要跨行,那么这个时候,理所应当的就要想到开窗函数了。

    SELECT
                    U.USER_NAME,
                    R.ID,
                    R.SIGN_ADDRESS,
                    R.CREATE_TIME,
                CASE
                        WHEN MIN(DATE_FORMAT( R.CREATE_TIME, '%H%i' )) over(partition by U.USER_NAME)  > 0830 THEN '迟到' 
                        WHEN MAX(DATE_FORMAT( R.CREATE_TIME, '%H%i' )) over(partition by U.USER_NAME)  < 1830 THEN '早退' 
                         ELSE '正常打卡' 
                            END 
                            FROM
                                T_REMOTE_SIGN_DETAILS R
                                LEFT JOIN T_USER U ON U.ID = R.USER_ID
                                LEFT JOIN T_SCHOOL S ON S.ID = U.SCHOOL_ID 
                            WHERE
                                DATE_FORMAT( R.CREATE_TIME, '%Y%M' ) = DATE_FORMAT( NOW(), '%Y%M' ) 
                                AND S.ID = '270000000109'
    

    但是,mysql要8.0以上版本才支持,否则你就得写个子查询先把最小最大查出来,再去关联到原数据了

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 3月26日
  • 已采纳回答 3月18日
  • 创建了问题 3月17日

悬赏问题

  • ¥15 微信会员卡等级和折扣规则
  • ¥15 微信公众平台自制会员卡可以通过收款码收款码收款进行自动积分吗
  • ¥15 随身WiFi网络灯亮但是没有网络,如何解决?
  • ¥15 gdf格式的脑电数据如何处理matlab
  • ¥20 重新写的代码替换了之后运行hbuliderx就这样了
  • ¥100 监控抖音用户作品更新可以微信公众号提醒
  • ¥15 UE5 如何可以不渲染HDRIBackdrop背景
  • ¥70 2048小游戏毕设项目
  • ¥20 mysql架构,按照姓名分表
  • ¥15 MATLAB实现区间[a,b]上的Gauss-Legendre积分