SQL Server年月搜索方法及MySQL转T-SQL日期函数报错解决
嘿,我来帮你搞定这两个SQL相关的问题,都是日常开发里很常见的场景,咱们一个个说清楚:
在SQL Server里,有几种实用的方式可以按年月筛选数据,我给你列几个常用的,你可以根据实际场景选择:
方法一:用YEAR()和MONTH()函数直接匹配
这种方式直观易懂,适合简单的筛选场景:SELECT * FROM 你的表名 WHERE YEAR(日期列) = 2017 AND MONTH(日期列) = 9;注意:如果你的日期列有索引,这种写法可能会导致索引失效(因为函数包裹了列),数据量大的时候要谨慎使用。
方法二:用FORMAT()函数格式化日期为年月字符串
和MySQL的DATE_FORMAT逻辑类似,SQL Server的FORMAT()可以直接把日期转成YYYY-MM格式:SELECT * FROM 你的表名 WHERE FORMAT(日期列, 'yyyy-MM') = '2017-09';同样,这个方法也会因为函数处理列,可能影响索引效率,小数据量用起来没问题。
方法三:构造日期范围(推荐,性能最优)
这种方式通过指定目标年月的起始和结束日期,直接匹配日期列,能利用索引,数据量大的时候首选:SELECT * FROM 你的表名 WHERE 日期列 >= '2017-09-01' AND 日期列 < '2017-10-01';原理是匹配所有2017年9月1日及以后,且早于10月1日的记录,完美覆盖整个9月的所有时间点,性能最好。
你遇到的问题是因为SQL Server没有DATE_FORMAT这个内置函数,咱们把它替换成SQL Server支持的写法就行,而且同样推荐用性能更好的日期范围方式来改写,我给你两种方案:
方案一:替换为FORMAT()函数(和原MySQL逻辑最接近)
把DATE_FORMAT(t.period,"%Y-%m")换成FORMAT(t.period, 'yyyy-MM'),完整的T-SQL语句如下:
SELECT t.id, t.value, t.branch_id, k.name FROM tb_target as t LEFT JOIN tb_keyindicator as k ON k.id = t.keyindicator_id WHERE t.branch_id IN ('241') AND FORMAT(t.period, 'yyyy-MM') = '2017-09';
方案二:使用日期范围查询(推荐,性能更优)
如果tb_target表的period列有索引,强烈建议用这种方式,避免函数处理列导致索引失效:
SELECT t.id, t.value, t.branch_id, k.name FROM tb_target as t LEFT JOIN tb_keyindicator as k ON k.id = t.keyindicator_id WHERE t.branch_id IN ('241') AND t.period >= '2017-09-01' AND t.period < '2017-10-01';
另外,如果你不想用FORMAT,也可以用字符串拼接的方式实现年月格式化,比如:
AND CONCAT(YEAR(t.period), '-', RIGHT('0' + CAST(MONTH(t.period) AS VARCHAR(2)), 2)) = '2017-09'
不过这种写法和FORMAT一样,都会对period列做函数处理,性能不如日期范围的方式。
内容的提问来源于stack exchange,提问作者Nikul Panchal

