我有每种产品库存的每周数据。我想按年-月对其进行分组,并获得每个月的第一个值。换句话说,我想获取每个月的期初存货,而不管该月的哪一天。
+------------+---------+
| MyDate | MyValue |
+------------+---------+
| 2018-01-06 | 2 |*
| 2018-01-13 | 7 |
| 2018-01-20 | 5 |
| 2018-01-27 | 2 |
| 2018-02-03 | 3 |*
| 2018-02-10 | 10 |
| 2018-02-17 | 6 |
| 2018-02-24 | 4 |
| 2018-03-03 | 7 |*
| 2018-03-10 | 5 |
| 2018-03-17 | 3 |
| 2018-03-24 | 4 |
| 2018-03-31 | 6 |
+------------+---------+
所需结果:
+----------------+---------+
| FirstDayOfMonth| MyValue |
+----------------+---------+
| 2018-01-01 | 2 |
| 2018-02-01 | 3 |
| 2018-03-01 | 7 |
+----------------+---------+
我认为这可能有效,但无效。
select
[product],
datefromparts(year([MyDate]), month([MyDate]), 1),
FIRST_VALUE(MyValue) OVER (PARTITION BY [Product], YEAR([MyDate]), MONTH([MyDate]) ORDER BY [MyDate] ASC) AS MyValue
from
MyTable
group by
[Product],
YEAR([MyDate]), MONTH([MyDate])
修改。谢谢。我问题中的重点不是如何获得每月的第一天。我知道有不同的技术。
重音是如何获得当月的FIRST值(期初存货)。如果有机会一口气拿下期末存货,那就太好了。基于ROW_NUMBER
的答案不允许一口气收尾,需要两次加入。
接受答案后进行编辑
请考虑约翰·卡佩莱蒂(John Cappelletti)的回答,以代替被接受的回答:https://stackoverflow.com/a/53559750/1903793
答案 0 :(得分:3)
您可以使用offsetTop
和apply
查找月份的最后一天并添加一天:
eomonth
答案 1 :(得分:3)
如果您选择了窗口函数路径,则实际上并不需要GROUP BY
:
SELECT Product, DATEADD(DAY, 1, EOMONTH(MyDate, -1)) AS Month, MyValue
FROM (
SELECT *, ROW_NUMBER() OVER (PARTITION BY Product, DATEADD(DAY, 1, EOMONTH(MyDate, -1)) ORDER BY MyDate) AS rn
FROM t
) AS x
WHERE rn = 1
更新
要获取该月的最后一行,只需执行UNION ALL <above query>
,但将order by子句更改为ORDER BY MyDate DESC
。这将使您每个产品每月两行。
答案 2 :(得分:1)
还可以使用rowNumber和cte。
WITH CTE as (
SELECT '2018-01-06' myDate, 2 Myvalue UNION ALL
SELECT '2018-01-13', 7 UNION ALL
SELECT '2018-01-20', 5 UNION ALL
SELECT '2018-01-27', 2 UNION ALL
SELECT '2018-02-03', 3 UNION ALL
SELECT '2018-02-10', 10 UNION ALL
SELECT '2018-02-17', 6 UNION ALL
SELECT '2018-02-24', 4 UNION ALL
SELECT '2018-03-03', 7 UNION ALL
SELECT '2018-03-10', 5 UNION ALL
SELECT '2018-03-17', 3 UNION ALL
SELECT '2018-03-24', 4 UNION ALL
SELECT '2018-03-31', 6),
CTE2 as (SELECT *
, Row_Number() over (partition by DATEADD(month, DATEDIFF(month, 0, MyDate), 0) order by myDate) RN
FROM CTE)
SELECT DATEADD(month, DATEDIFF(month, 0, MyDate), 0), MyValue
FROM cte2
WHERE RN = 1
给我们:
+----+---------------------+---------+
| | (No column name) | MyValue |
+----+---------------------+---------+
| 1 | 01.01.2018 00:00:00 | 2 |
| 2 | 01.02.2018 00:00:00 | 3 |
| 3 | 01.03.2018 00:00:00 | 7 |
+----+---------------------+---------+
答案 3 :(得分:1)
另一个选择是使用WITH TIES,然后在日期上作些欺骗
示例
Select top 1 with ties
MyDate = convert(varchar(7),MyDate,120)+'-01'
,MyValue
from YourTable
Order By Row_Number() over (Partition By convert(varchar(7),MyDate,120) Order By MyDate)
返回
MyDate MyValue
2018-01-01 2
2018-02-01 3
2018-03-01 7