<?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.StockDailyDao">

    <insert id="insertOrUpdateList" parameterType="list">
        INSERT INTO stock_daily
            (ts_code, trade_date, "open", high, low, "close", pre_close, "change", pct_chg, vol, amount)
        VALUES
        <foreach collection="list" item="item" index="index" separator=",">
            (#{item.ts_code}, 
             <!-- 数据库内其实是 timestamp 格式，因为 StockValue 用的是 LocalDateTime，如果设置成
                  date 格式的话，转换成 LocalDateTime 会出错 -->
             TO_DATE(#{item.trade_date}, 'YYYYMMDD'),
             #{item.open},
             #{item.high},
             #{item.low},
             #{item.close},
             #{item.pre_close},
             #{item.change},
             #{item.pct_chg},
             #{item.vol},
             #{item.amount}
             )
        </foreach>
        ON CONFLICT (ts_code, trade_date) DO UPDATE SET
            ts_code = EXCLUDED.ts_code,
            trade_date = EXCLUDED.trade_date,
            "open" = EXCLUDED.open,
            high = EXCLUDED.high,
            low = EXCLUDED.low,
            "close" = EXCLUDED.close,
            pre_close = EXCLUDED.pre_close,
            "change" = EXCLUDED."change",
            pct_chg = EXCLUDED.pct_chg,
            vol = EXCLUDED.vol,
            amount = EXCLUDED.amount
    </insert>
    
    <select id="getLatestTradeDate" resultType="java.time.LocalDateTime">
        SELECT
            MAX(trade_date)
        FROM
            stock_daily
        WHERE
            1 = 1
            <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 trade_date
        FROM
            stock_daily
        WHERE
            1 = 1
            <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 trade_date
            FROM   stock_daily
            WHERE  1 = 1
            <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 date >= #{stockInfo.listDate}
        </if>
        AND date &lt; CURRENT_DATE + INTERVAL '1 DAY'
        ORDER BY date ASC
    </select>
    
    <sql id="qfqFields">
        s.*, s.trade_date as "date",
        s.adj_factor / t.adj_factor AS qfq_factor,
        d.open * s.adj_factor / t.adj_factor AS open,
        d.high * s.adj_factor / t.adj_factor AS high,
        d.low * s.adj_factor / t.adj_factor AS low,
        d.close * s.adj_factor / t.adj_factor AS close,
        d.vol, d.amount, d.pct_chg, d."change"
    </sql>
    
    <select id="getQfqDaily" 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_daily d
            ON ( 
                d.trade_date = s.trade_date 
            AND d.ts_code = #{stockCode}
            <if test="startDate != null">
               AND d.trade_date &gt;= #{startDate}
            </if>
            <if test="endDate != null">
               AND d.trade_date &lt;= #{endDate}
            </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 d.open IS NOT NULL 
        ORDER BY
            s.trade_date ASC
    </select>

    <select id="getQfqDailyBefore" 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_daily d
            ON ( 
                d.trade_date = s.trade_date 
            AND d.ts_code = #{stockCode}
            <if test="endDate != null">
               AND d.trade_date &lt;= #{endDate}
            </if>
        ) 
        WHERE
            s.ts_code = #{stockCode}
            <if test="endDate != null">
               AND s.trade_date &lt;= #{endDate}
            </if>
            AND d.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>
    
    
    <select id="getQfqDailyAfter" 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 >= #{startDate}
                        </if>
                )
                AND
                    t.ts_code = #{stockCode}
                    <if test="startDate != null">
                       AND t.trade_date >= #{startDate}
                    </if>
            )
        LEFT JOIN
            stock_daily d
            ON ( 
                d.trade_date = s.trade_date 
            AND d.ts_code = #{stockCode}
            <if test="startDate != null">
               AND d.trade_date >= #{startDate}
            </if>
        ) 
        WHERE
            s.ts_code = #{stockCode}
            <if test="startDate != null">
               AND s.trade_date >= #{startDate}
            </if>
            AND d.open IS NOT NULL 
        ORDER BY
            s.trade_date ASC
        <if test="after != null and after != 0L">
        LIMIT #{after}
        </if>
    </select>
    
    <select id="getExQfqDailyAfter" resultType="link.at17.mid.tushare.data.models.StockValueEx">
        SELECT
            <include refid="qfqFields"/>,
            b.turnover_rate AS turnoverRate,
            b.turnover_rate_f 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="startDate != null">
                           AND o.trade_date >= #{startDate}
                        </if>
                )
                AND
                    t.ts_code = #{stockCode}
                    <if test="startDate != null">
                       AND t.trade_date >= #{startDate}
                    </if>
            )
        LEFT JOIN
            stock_daily d
            ON ( 
                d.trade_date = s.trade_date 
            AND d.ts_code = #{stockCode}
            <if test="startDate != null">
               AND d.trade_date >= #{startDate}
            </if>
            )
        LEFT JOIN
            stock_daily_basic_tushare b
            ON  (
                b.trade_date = s.trade_date
                AND b.ts_code = #{stockCode}
                <if test="startDate != null">
                   AND b.trade_date >= #{startDate}
                </if>
            )
        WHERE
            s.ts_code = #{stockCode}
            <if test="startDate != null">
               AND s.trade_date >= #{startDate}
            </if>
            AND d.open IS NOT NULL 
        ORDER BY
            s.trade_date ASC
        <if test="after != null and after != 0L">
        LIMIT #{after}
        </if>
    </select>
    
    <select id="getExQfqDailyBefore" resultType="link.at17.mid.tushare.data.models.StockValueEx">
        SELECT * FROM (
        SELECT
            <include refid="qfqFields"/>,
            b.turnover_rate AS turnoverRate,
            b.turnover_rate_f 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_daily d
            ON ( 
                d.trade_date = s.trade_date 
            AND d.ts_code = #{stockCode}
            <if test="endDate != null">
               AND d.trade_date &lt;= #{endDate}
            </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 d.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>
    
    <select id="getExDailyBefore" resultType="link.at17.mid.tushare.data.models.StockValueEx">
        SELECT * FROM (
        SELECT
            d.*, d.trade_date as "date",
            b.turnover_rate AS turnoverRate,
            b.turnover_rate_f AS turnoverRateF,
            b.volume_ratio AS volumeRatio,
            b.pe,
            b.pe_ttm AS peTtm,
            b.pb,
            b.ps,
            b.ps_ttm AS psTtm,           <!-- 市销率(TTM)    -->
            b.dv_ratio AS dvRatio,       <!-- 股息率(%)      -->
            b.dv_ttm AS dvTtm,           <!-- 股息率(TTM, %) -->
            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_daily d
        LEFT JOIN
            stock_daily_basic_tushare b
            ON  (
                b.trade_date = d.trade_date
                AND b.ts_code = #{stockCode}
                <if test="endDate != null">
                   AND b.trade_date &lt;= #{endDate}
                </if>
            )
        WHERE
            d.ts_code = #{stockCode}
            <if test="endDate != null">
               AND d.trade_date &lt;= #{endDate}
            </if>
            AND d.open IS NOT NULL 
        ORDER BY
            d.trade_date DESC
        <if test="before != null and before != 0L">
        LIMIT #{before}
        </if>
        ) f ORDER BY f.trade_date ASC
    </select>
</mapper>
