<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="link.at17.mid.tushare.dao.StockMinuteDao">

    <insert id="insertOrUpdateList" parameterType="list">
        INSERT INTO stock_minute
            (ts_code, trade_time, open, high, low, close, vol, amount, freq)
        VALUES
        <foreach collection="list" item="item" index="index" separator=",">
            (#{item.ts_code}, 
             STR_TO_DATE(#{item.trade_time}, '%Y-%m-%d %H:%i:%s'),
             #{item.open},
             #{item.high},
             #{item.low},
             #{item.close},
             #{item.vol},
             #{item.amount},
             ${stockSpan.eastMoneyCode}
             )
        </foreach>
        ON CONFLICT (ts_code, trade_time, freq) DO UPDATE SET
            ts_code = EXCLUDED.ts_code,
            trade_time = EXCLUDED.trade_time,
            open = EXCLUDED.open,
            high = EXCLUDED.high,
            low = EXCLUDED.low,
            close = EXCLUDED.close,
            vol = EXCLUDED.vol,
            amount = EXCLUDED.amount,
            freq = EXCLUDED.freq
    </insert>
    
    <select id="getLatestTradeDate" resultType="java.time.LocalDateTime">
        SELECT
            DATE(MAX(trade_time))
        FROM
            stock_minute
        WHERE
            1 = 1
            AND freq = ${stockSpan.eastMoneyCode}
            <if test="stockInfo != null and stockInfo.getTsCode() != null and stockInfo.getTsCode() != ''">
                AND ts_code = #{stockInfo.tsCode}
            </if>
    </select>
    
    <select id="getAllTradeDates" resultType="java.time.LocalDateTime">
        SELECT
            DISTINCT DATE(trade_time)
        FROM
            stock_minute
        WHERE
            1 = 1
            AND freq = ${stockSpan.eastMoneyCode}
            <if test="stockInfo != null and stockInfo.getTsCode() != null and stockInfo.getTsCode() != ''">
                AND ts_code = #{stockInfo.tsCode}
            </if>
    </select>
    
    <select id="getAllMissingDates" resultType="java.time.LocalDateTime">
        SELECT DISTINCT date 
        FROM   stock_calendar
        WHERE  stock_calendar.is_open = TRUE
        <if test="stockInfo != null and stockInfo.getTsCode() != null and stockInfo.getTsCode() != ''">
            <choose>
                <when test="stockInfo.getTsCode().endsWith('SZ')">
                    AND stock_calendar.exchange = 'SZSE'
                </when>
                <when test="stockInfo.getTsCode().endsWith('SH')">
                    AND stock_calendar.exchange = 'SSE'
                </when>
                <otherwise></otherwise>
            </choose>
        </if>
        AND date NOT IN (
	        SELECT
	            DISTINCT DATE(trade_time) AS date
	        FROM
	            stock_minute
	        WHERE 1 = 1
	            AND freq = ${stockSpan.eastMoneyCode}
	        <if test="stockInfo != null and stockInfo.getTsCode() != null and stockInfo.getTsCode() != ''">
	            AND ts_code = #{stockInfo.tsCode}
	        </if>
	        <if test="stockInfo != null and stockInfo.getListDate() != null">
	            AND trade_time >= #{stockInfo.listDate}
	        </if>
	        GROUP BY date
	        HAVING COUNT(*) = (240 / #{stockSpan.min} + 1)
        )
        <if test="stockInfo != null and stockInfo.getListDate() != null">
            AND date >= #{stockInfo.listDate}
        </if>
        <!-- For minutes data only, there're no data before this date -->
        AND date >= '2009-01-05'
        AND date &lt; CURRENT_DATE + INTERVAL '1 DAY'
        ORDER BY date ASC
    </select>
    
    <sql id="qfqFields">
	    s.*,
	    m.trade_time AS "date",
	    s.adj_factor / t.adj_factor AS qfq_factor,
	    m."open" * s.adj_factor / t.adj_factor AS "open",
	    m.high * s.adj_factor / t.adj_factor AS high,
	    m.low * s.adj_factor / t.adj_factor AS low,
	    m."close" * s.adj_factor / t.adj_factor AS "close",
	    m.vol, m.amount, m.freq
    </sql>
    
    <select id="getQfqMinute" resultType="link.at17.mid.tushare.data.models.StockValue">
        SELECT
            <include refid="qfqFields"/>
        FROM
            stock_adjust_factor_tushare s
        LEFT JOIN
            stock_adjust_factor_tushare t 
            ON (
                t.trade_date = ( 
                    SELECT
                        MAX(o.trade_date)
                    FROM
                        stock_adjust_factor_tushare o 
                    WHERE
                        o.ts_code = #{stockCode}
                        <if test="startDate != null">
                           AND o.trade_date &gt;= #{startDate}
                        </if>
                        <if test="endDate != null">
                           AND o.trade_date &lt;= #{endDate}
                        </if>
                )
                AND
                    t.ts_code = #{stockCode}
                    <if test="startDate != null">
                       AND t.trade_date &gt;= #{startDate}
                    </if>
                    <if test="endDate != null">
                       AND t.trade_date &lt;= #{endDate}
                    </if>
            )
        LEFT JOIN
            stock_minute m ON (
            m.trade_time BETWEEN s.trade_date AND s.trade_date + INTERVAL '1 DAY' 
            AND m.ts_code = #{stockCode}
            AND m.freq = ${stockSpan.eastMoneyCode}
            <if test="startDate != null">
               AND m.trade_time &gt;= #{startDate}
            </if>
            <if test="endDate != null">
               AND m.trade_time &lt;= #{endDate} + INTERVAL '1 DAY' 
            </if>
        ) 
        WHERE
            s.ts_code = #{stockCode}
            <if test="startDate != null">
               AND s.trade_date &gt;= #{startDate}
            </if>
            <if test="endDate != null">
               AND s.trade_date &lt;= #{endDate}
            </if>
            AND m.freq = ${stockSpan.eastMoneyCode}
            AND m."open" IS NOT NULL 
        ORDER BY
            m.trade_time ASC
    </select>

    <select id="getQfqMinuteBefore" resultType="link.at17.mid.tushare.data.models.StockValue">
        SELECT * FROM (
        SELECT
            <include refid="qfqFields"/>
        FROM
            stock_adjust_factor_tushare s
        LEFT JOIN
            stock_adjust_factor_tushare t 
            ON (
                t.trade_date = ( 
                    SELECT
                        MAX(o.trade_date)
                    FROM
                        stock_adjust_factor_tushare o 
                    WHERE
                        o.ts_code = #{stockCode}
                        <if test="endDate != null">
                           AND o.trade_date &lt;= #{endDate}
                        </if>
                )
                AND
                    t.ts_code = #{stockCode}
                    <if test="endDate != null">
                       AND t.trade_date &lt;= #{endDate}
                    </if>
            )
        LEFT JOIN
            stock_minute m
            ON ( 
                m.trade_time BETWEEN s.trade_date AND s.trade_date + INTERVAL '1 DAY' 
            AND m.freq = ${stockSpan.eastMoneyCode}
            AND m.ts_code = #{stockCode}
            <if test="endDate != null">
               AND m.trade_trade &lt;=  #{endDate} + INTERVAL '1 DAY' 
            </if>
        )
        WHERE
            s.ts_code = #{stockCode}
            <if test="endDate != null">
               AND s.trade_date &lt;= #{endDate}
            </if>
            AND m.freq = ${stockSpan.eastMoneyCode}
            AND m.open IS NOT NULL 
        ORDER BY
            m.trade_time DESC
        <if test="before != null and before != 0L">
        LIMIT #{before}
        </if>
        ) f ORDER BY f.date ASC
    </select>
    
    <select id="getExQfqMinuteBefore" resultType="link.at17.mid.tushare.data.models.StockValueEx">
        SELECT * FROM (
        SELECT
            <include refid="qfqFields"/>,
            m.vol / b.total_share AS turnoverRate,
            m.vol / b.float_share AS turnoverRateF,
            b.volume_ratio AS volumeRatio,
            b.pe,
            b.pe_ttm AS peTtm,
            b.pb,
            b.ps,
            b.ps_ttm AS psTtm,
            b.dv_ratio AS dvRatio,
            b.dv_ttm AS dvTtm,
            b.total_share AS totalShare,
            b.float_share AS floatShare,
            b.free_share AS freeShare,
            b.total_mv AS totalMv,
            b.circ_mv AS circMv
        FROM
            stock_adjust_factor_tushare s
        LEFT JOIN
            stock_adjust_factor_tushare t 
            ON (
                t.trade_date = ( 
                    SELECT
                        MAX(o.trade_date)
                    FROM
                        stock_adjust_factor_tushare o 
                    WHERE
                        o.ts_code = #{stockCode}
                        <if test="endDate != null">
                           AND o.trade_date &lt;= #{endDate}
                        </if>
                )
                AND
                    t.ts_code = #{stockCode}
                    <if test="endDate != null">
                       AND t.trade_date &lt;= #{endDate}
                    </if>
            )
        LEFT JOIN
            stock_minute m
            ON ( 
                m.trade_time BETWEEN s.trade_date AND s.trade_date + INTERVAL '1 DAY' 
            AND m.freq = ${stockSpan.eastMoneyCode}
            AND m.ts_code = #{stockCode}
            <if test="endDate != null">
               AND m.trade_trade &lt;=  #{endDate} + INTERVAL '1 DAY' 
            </if>
        )
        LEFT JOIN
            stock_daily_basic_tushare b
            ON  (
                b.trade_date = s.trade_date
                AND b.ts_code = #{stockCode}
                <if test="endDate != null">
                   AND b.trade_date &lt;= #{endDate}
                </if>
            )
        WHERE
            s.ts_code = #{stockCode}
            <if test="endDate != null">
               AND s.trade_date &lt;= #{endDate}
            </if>
            AND m.freq = ${stockSpan.eastMoneyCode}
            AND m.open IS NOT NULL 
        ORDER BY
            s.trade_date DESC
        <if test="before != null and before != 0L">
        LIMIT #{before}
        </if>
        ) f ORDER BY f.trade_date ASC
    </select>
</mapper>
