MySQL查询用DISTINCT仍返回重复Date字段值的解决方法咨询
问题原因分析
- 你之前使用
DISTINCT无效的原因是:DISTINCT是对查询返回的所有字段的组合值去重,同日期下价格字段值不同时,整行记录的组合值不重复,因此不会被去重。 - 你尝试的
UNION查询本身存在语法错误:UNION要求前后两个子查询返回的字段数量、字段类型完全匹配,你第一个子查询仅返回DATE1个字段,第二个返回4个价格字段,根本无法正常执行。
解决方案
首先修正原SQL里的不规范写法:原WHERE条件中AND Date、AND Open这类写法是判断字段非空非0的简写,建议统一写成字段 IS NOT NULL,逻辑更清晰也避免隐式转换问题。
方案1:MySQL 8.0+ 版本(推荐,性能更优)
使用ROW_NUMBER()窗口函数,按日期分组,按你表中自增主键(假设主键名为id,如果有其他表示插入顺序的字段替换即可)排序取每组第一条:
SELECT Date, Open, High, Low, Close FROM ( SELECT Date, Open, High, Low, Close, ROW_NUMBER() OVER (PARTITION BY Date ORDER BY id ASC) AS rn FROM symbolsv2 WHERE ticker=? AND `intval`=? AND Date>=? AND Date IS NOT NULL AND Open IS NOT NULL AND High IS NOT NULL AND Low IS NOT NULL AND Close IS NOT NULL ) AS t WHERE rn = 1 ORDER BY Date ASC
把你PHP里prepare的SQL替换成上面的即可。
方案2:MySQL 5.x 版本(兼容老版本)
使用子查询匹配每个日期对应的最早插入记录的主键:
SELECT Date, Open, High, Low, Close FROM symbolsv2 s INNER JOIN ( SELECT MIN(id) AS first_id FROM symbolsv2 WHERE ticker=? AND `intval`=? AND Date>=? AND Date IS NOT NULL AND Open IS NOT NULL AND High IS NOT NULL AND Low IS NOT NULL AND Close IS NOT NULL GROUP BY Date ) AS t ON s.id = t.first_id ORDER BY s.Date ASC
注意:如果你的表没有自增主键id,可以把ORDER BY id ASC替换为你能判断记录插入先后的字段,比如爬虫抓取时间字段,如果没有时间字段也可以直接按价格字段排序,只要符合你“第一条”的定义即可。
(可选)直接删除表中的重复数据
如果你需要永久删除表中同日期的冗余重复记录,执行以下SQL即可(执行前建议先备份数据):
DELETE s1 FROM symbolsv2 s1 JOIN symbolsv2 s2 ON s1.ticker = s2.ticker AND s1.intval = s2.intval AND s1.Date = s2.Date AND s1.id > s2.id;
执行后每个日期仅会保留id最小的第一条记录,后续查询就不需要再做去重处理了。
内容的提问来源于stack exchange,提问作者user17153595
相关产品推荐
相关产品推荐

