<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.dromara.mapper.SenEventsMapper">

    <select id="selectEventsCount" resultType="java.util.HashMap">
        SELECT
        COUNT(*) AS totalEvents,
        SUM(CASE WHEN event_category = '1' THEN 1 ELSE 0 END) AS importantEvents,
        SUM(CASE WHEN deal_status = '0' THEN 1 ELSE 0 END) AS unprocessedEvents
        FROM
        sen_events
    </select>
    <select id="importantEventsStat" resultType="java.util.HashMap">
        SELECT
        (SELECT dic.dict_label from sys_dict_data dic WHERE dic.dict_type='event_type' AND dic.dict_value=event_type)
        AS name,
        COUNT(event_type) AS value
        FROM sen_events
        ${ew.getCustomSqlSegment}
        GROUP BY event_type
        ORDER BY name
    </select>
    <select id="motorInLanesTop10" resultType="java.util.HashMap">
        SELECT point_name AS pointName, COUNT(*) AS eventCount
        FROM sen_events
        ${ew.getCustomSqlSegment}
        GROUP BY point_name
        ORDER BY eventCount DESC
        LIMIT 10
    </select>
    <select id="motorInLanesCount" resultType="java.util.HashMap">
        SELECT COUNT(*) AS totalCount
        FROM sen_events
        ${ew.getCustomSqlSegment}
    </select>
    <select id="eventPercentTop10" resultType="java.util.Map">
        WITH EventTypeCounts AS (
        SELECT
        event_type,
        COUNT(*) AS event_count
        FROM
        sen_events
        GROUP BY
        event_type
        )
        SELECT
        (SELECT dic.dict_label from sys_dict_data dic where dic.dict_type='event_type' AND dic.dict_value=event_type) AS
        name,
        event_count AS value
        FROM
        EventTypeCounts
        ORDER BY
        event_count DESC
        LIMIT 10
    </select>
    <select id="eventMonthCount" resultType="java.util.Map">
        -- 使用子查询来筛选近30日内的记录
        WITH RecentEvents AS (
        SELECT *
        FROM sen_events
        WHERE create_time >= NOW() - INTERVAL 30 DAY
        ),

        -- 计算每个事件类型的数量
        EventTypeCounts AS (
        SELECT
        event_type,
        COUNT(*) AS event_count
        FROM
        RecentEvents
        GROUP BY
        event_type
        )

        -- 最终查询
        SELECT
        (SELECT dic.dict_label from sys_dict_data dic where dic.dict_type='event_type' AND dic.dict_value=event_type) AS
        name,
        event_count AS value
        FROM
        EventTypeCounts
        ORDER BY
        event_count DESC
    </select>
    <select id="eventDayCount" resultType="java.util.Map">
        -- 生成最近30天的日期序列
        WITH DateList AS (
        SELECT CURDATE() - INTERVAL n DAY AS date
        FROM (
        -- 生成0到29的数字序列
        SELECT n
        FROM (
        SELECT 0 UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3
        UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7
        UNION ALL SELECT 8 UNION ALL SELECT 9 UNION ALL SELECT 10 UNION ALL SELECT 11
        UNION ALL SELECT 12 UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL SELECT 15
        UNION ALL SELECT 16 UNION ALL SELECT 17 UNION ALL SELECT 18 UNION ALL SELECT 19
        UNION ALL SELECT 20 UNION ALL SELECT 21 UNION ALL SELECT 22 UNION ALL SELECT 23
        UNION ALL SELECT 24 UNION ALL SELECT 25 UNION ALL SELECT 26 UNION ALL SELECT 27
        UNION ALL SELECT 28 UNION ALL SELECT 29
        ) numbers(n)
        ) AS dates
        ),

        -- 获取所有事件类型
        EventTypes AS (
        SELECT DISTINCT event_type
        FROM sen_events
        ),

        -- 使用左连接来确保每一天都有记录，即使那天没有数据
        FullData AS (
        SELECT dl.date,
        et.event_type,
        COUNT(se.id) AS event_count
        FROM DateList dl
        CROSS JOIN EventTypes et
        LEFT JOIN sen_events se ON dl.date = DATE(se.create_time) AND et.event_type = se.event_type
        GROUP BY dl.date, et.event_type
        )

        -- 查询最近30天的每一天及其事件类型和计数
        SELECT date, (SELECT dic.dict_label from sys_dict_data dic where dic.dict_type='event_type' AND
        dic.dict_value=event_type) AS name, event_count AS value
        FROM FullData
        ORDER BY date ASC, event_type ASC;
    </select>
    <select id="pointEventsStat" resultType="java.util.HashMap">
        SELECT
        area_name,
        COUNT( id ) AS event_count
        FROM
        sen_events
        WHERE
        area_name IS NOT NULL
        <if test="ew.getSqlSegment != null and ew.getSqlSegment != ''">
            AND ${ew.getSqlSegment}
        </if>
        GROUP BY
        area_name
        ORDER BY
        event_count DESC
        LIMIT 10
    </select>
    <select id="regionEventsStat" resultType="java.util.HashMap">
        SELECT
        sa2.area_name AS name,
        COUNT( ev.id ) AS value
        FROM
        sen_events ev
        LEFT JOIN sys_area sa ON sa.area_id = ev.area_id
        LEFT JOIN sys_area sa2 ON sa2.area_id = sa.parent_id
        WHERE ev.area_id IS NOT NULL
        <if test="dateType == 1">
            AND DATE(ev.create_time) = CURDATE()
        </if>
        <if test="dateType == 7">
            AND ev.create_time >= DATE_SUB(CURDATE(), INTERVAL 7 DAY)
        </if>
        <if test="dateType == 30">
            AND ev.create_time >= DATE_SUB(CURDATE(), INTERVAL 30 DAY)
        </if>
        GROUP BY
        sa2.area_name
        ORDER BY
        value DESC
        LIMIT 10
    </select>
    <select id="minuteEventsStat" resultType="java.util.HashMap">
        SELECT
        DATE_FORMAT(create_time, '%H:%i') AS time_format,
        COUNT(id) AS count
        FROM
        sen_events
        WHERE
        create_time >= CURDATE()
        AND create_time &lt; (CURDATE() + INTERVAL 1 DAY)
        <if test="ew.getSqlSegment != null and ew.getSqlSegment != ''">
            AND ${ew.getSqlSegment}
        </if>
        GROUP BY
        DATE_FORMAT(create_time, '%H:%i')
        ORDER BY
        time_format
    </select>
    <select id="eventsDatasourceStat" resultType="java.util.HashMap">
        SELECT
        datasource,
        COUNT(*) AS count
        FROM
        sen_events
        WHERE
        datasource IS NOT NULL
        <if test="ew.getSqlSegment != null and ew.getSqlSegment != ''">
            AND ${ew.getSqlSegment}
        </if>
        GROUP BY
        datasource;
    </select>
    <select id="eventsHourStat" resultType="java.util.HashMap">
        WITH -- 生成一天内的每个小时
        Hours AS (
        SELECT
        CONCAT( LPAD( CAST( HOUR AS CHAR ), 2, '0' ), ':00:00' ) AS hour_of_day
        FROM
        (
        SELECT
        0 AS HOUR UNION ALL
        SELECT
        1 UNION ALL
        SELECT
        2 UNION ALL
        SELECT
        3 UNION ALL
        SELECT
        4 UNION ALL
        SELECT
        5 UNION ALL
        SELECT
        6 UNION ALL
        SELECT
        7 UNION ALL
        SELECT
        8 UNION ALL
        SELECT
        9 UNION ALL
        SELECT
        10 UNION ALL
        SELECT
        11 UNION ALL
        SELECT
        12 UNION ALL
        SELECT
        13 UNION ALL
        SELECT
        14 UNION ALL
        SELECT
        15 UNION ALL
        SELECT
        16 UNION ALL
        SELECT
        17 UNION ALL
        SELECT
        18 UNION ALL
        SELECT
        19 UNION ALL
        SELECT
        20 UNION ALL
        SELECT
        21 UNION ALL
        SELECT
        22 UNION ALL
        SELECT
        23
        ) AS hours
        ),-- 统计每小时内的事件数量
        EventCounts AS (
        SELECT
        CONCAT( LPAD( HOUR ( create_time ), 2, '0' ), ':00:00' ) AS hour_of_day,
        COUNT(*) AS num_events
        FROM
        sen_events
        ${ew.getCustomSqlSegment}
        GROUP BY
        hour_of_day
        ) -- 左连接生成的时间戳与事件统计
        SELECT
        h.hour_of_day AS hour,
        COALESCE ( ec.num_events, 0 ) AS events
        FROM
        Hours h
        LEFT JOIN EventCounts ec ON h.hour_of_day = ec.hour_of_day
        ORDER BY
        hour
    </select>
    <select id="eventsDealRateStat" resultType="java.util.HashMap">
        WITH
        -- 统计每个事件类型的总事件数和已处理事件数
        EventStats AS (
        SELECT
        event_type,
        COUNT(*) AS totalEvents,
        SUM(CASE WHEN deal_status = 1 THEN 1 ELSE 0 END) AS dealtEvents
        FROM
        sen_events
        ${ew.getCustomSqlSegment}
        GROUP BY
        event_type
        )
        -- 计算处理率
        SELECT
        dict.dict_label AS eventType,
        totalEvents,
        dealtEvents,
        CASE
        WHEN totalEvents > 0 THEN (dealtEvents * 100 / totalEvents) ELSE 0
        END AS dealRate
        FROM
        EventStats se
        LEFT JOIN sys_dict_data dict ON dict.dict_type='event_type' AND dict.dict_value = se.event_type
        ORDER BY
        dict.dict_label;
    </select>
    <select id="cycleEventStat" resultType="java.util.Map">
        SELECT
        pointName,
        SUM(CASE WHEN event_type = 13 THEN count ELSE 0 END) AS nonMotorVehicleOnLane,
        SUM(CASE WHEN event_type = 14 THEN count ELSE 0 END) AS nonMotorVehicleNoHelmet,
        SUM(CASE WHEN event_type = 15 THEN count ELSE 0 END) AS pedestrianOnLane
        FROM (
        SELECT
        point_name AS pointName,
        event_type,
        COUNT(*) AS count
        FROM
        sen_events
        WHERE
        event_type IN (13, 14, 15)
        <if test="ew.getSqlSegment != null and ew.getSqlSegment != ''">
            AND ${ew.getSqlSegment}
        </if>
        GROUP BY
        pointName, event_type
        ) sub
        GROUP BY
        pointName
        ORDER BY
        pointName
    </select>
    <select id="keyVehicleEventStat" resultType="java.util.Map">
        WITH plate_counts AS (
        SELECT
        seo.object_id,
        seo.object_type,
        seo.object_attr,
        se.event_type,
        COUNT( se.id ) AS event_count
        FROM
        sen_events_object seo
        LEFT JOIN sen_events se ON seo.event_id = se.id
        WHERE
        CAST( se.event_type AS UNSIGNED ) BETWEEN 5
        AND 12
        <if test="startDate!=null">
            AND DATE ( se.create_time ) >=${startDate}
        </if>
        <if test="endDate!=null">
            AND DATE ( se.create_time ) &lt;=${endDate}
        </if>
        GROUP BY
        seo.object_id,
        seo.object_type,
        seo.object_attr,
        se.event_type
        ),
        all_objects AS ( SELECT DISTINCT object_id, object_type, object_attr FROM sen_events_object seo   ${ew.getCustomSqlSegment}
        ) SELECT
        ao.object_id AS objectId,
        ao.object_type AS objectType,
        ao.object_attr AS objectAttr,
        COALESCE ( SUM( CASE WHEN pc.event_type = 5 THEN pc.event_count ELSE 0 END ), 0 ) AS eventCount5,
        COALESCE ( SUM( CASE WHEN pc.event_type = 6 THEN pc.event_count ELSE 0 END ), 0 ) AS eventCount6,
        COALESCE ( SUM( CASE WHEN pc.event_type = 7 THEN pc.event_count ELSE 0 END ), 0 ) AS eventCount7,
        COALESCE ( SUM( CASE WHEN pc.event_type = 8 THEN pc.event_count ELSE 0 END ), 0 ) AS eventCount8,
        COALESCE ( SUM( CASE WHEN pc.event_type = 9 THEN pc.event_count ELSE 0 END ), 0 ) AS eventCount9,
        COALESCE ( SUM( CASE WHEN pc.event_type = 10 THEN pc.event_count ELSE 0 END ), 0 ) AS eventCount10,
        COALESCE ( SUM( CASE WHEN pc.event_type = 11 THEN pc.event_count ELSE 0 END ), 0 ) AS eventCount11,
        COALESCE ( SUM( CASE WHEN pc.event_type = 12 THEN pc.event_count ELSE 0 END ), 0 ) AS eventCount12
        FROM
        all_objects ao
        LEFT JOIN plate_counts pc ON ao.object_id = pc.object_id
        AND ao.object_type = pc.object_type
        AND ao.object_attr = pc.object_attr
        GROUP BY
        objectId,
        objectType,
        objectAttr
        ORDER BY
        objectId
    </select>
</mapper>
