如何SQL查询有交易的当月最后一天?
How to SQL Query Last Day of the Month that has transaction?
我的这组数据如下:
+------+-------+-----+--------+
| Year | Month | Day | Amount |
+------+-------+-----+--------+
| 2019 | 01 | 01 | 10 |
| 2019 | 01 | 15 | 30 |
| 2019 | 01 | 29 | 40 |
| 2019 | 02 | 02 | 50 |
| 2019 | 02 | 22 | 60 |
| 2019 | 03 | 11 | 70 |
| 2019 | 03 | 31 | 80 |
+------+-------+-----+--------+
我只想查看每个月有交易的最后记录日。
我喜欢的显示结果应该是这样的:
+------+-------+--------+
| Year | Month | Amount |
+------+-------+--------+
| 2019 | 01 | 40 |
| 2019 | 02 | 60 |
| 2019 | 03 | 80 |
+------+-------+--------+
对于 Year
和 Month
的每个组合,您想获得最大的 Day
和 Amount
值:
SELECT Year, Month, max(Day) as Day, max(Amount) as Amount
FROM t
GROUP BY Year, Month;
请注意,出现在 SELECT
子句中但未出现在 GROUP BY
子句中的每一列都必须聚合(此处为 max
)。
也就是说,假设 Amount
对应于每天的总数,这就是您的示例所建议的。
如果您的 table 每天包含超过一个 Amount
,那么您还需要总结每天的金额。我会使用类似的东西:
SELECT Year, Month, max(Day) as Day, max(Amount) as Amount
FROM (
SELECT Year, Month, Day, sum(Amount) as Amount
FROM t
GROUP BY Year, Month, Day
) as tmp
GROUP BY Year, Month;
test me(在您的示例中再添加一笔金额)
或:
SELECT Year, Month, Day, sum(Amount) as Amount
FROM (
SELECT *, rank() over(partition by Year, Month order by Day desc) as r
FROM t
) as tmp
WHERE r = 1
GROUP BY Year, Month, Day;
请注意,您要在此处使用 rank()
而不是 row_number()
,因为您需要为领带(同一天)提供相同的排名标识符。
当然,如果你愿意,你可以将上面的任何查询包装成:
SELECT Year, Month, Amount
FROM (<query>) as q;
删除日期栏。
您可以使用行号来实现:
SELECT [Year], [Month], [Amount]
FROM (
SELECT ROW_NUMBER() OVER(PARTITION BY CONCAT(YEAR,MONTH) ORDER BY DAY DESC) rn, *
FROM table) t
WHERE rn = 1
一种方法是相关子查询:
select t.*
from t
where t.day = (select max(t2.day)
from t t2
where t2.year = t.year and t2.month = t.month
);
另一种常用方法使用 row_number()
:
select t.*
from (select t.*,
row_number() over (partition by year, month order by day desc) as seqnum
from t
) t
where seqnum = 1;
select year,month,amount from(SELECT year,month,max(day),amount FROM t GROUP BY year,month);
您可以在下方使用:
SELECT ROW_NUMBER() OVER(PARTITION BY YEAR, MONTH ORDER BY DAY DESC) as rn, *
FROM yourtable
QUALIFY rn = 1
使用 ROW_NUMBER() 函数:
with cte_order as (select year, month, amount,row_number() over(partition by month order by day desc) as identity_row from test1)
select 年、月、金额 cte_order 其中 identity_row = 1;
使用 QUALIFY() 函数:
select year, month, amount, day, row_number() over(partition by month order by day desc) as identity_row from test1 qualify identity_row = 1;
我的这组数据如下:
+------+-------+-----+--------+
| Year | Month | Day | Amount |
+------+-------+-----+--------+
| 2019 | 01 | 01 | 10 |
| 2019 | 01 | 15 | 30 |
| 2019 | 01 | 29 | 40 |
| 2019 | 02 | 02 | 50 |
| 2019 | 02 | 22 | 60 |
| 2019 | 03 | 11 | 70 |
| 2019 | 03 | 31 | 80 |
+------+-------+-----+--------+
我只想查看每个月有交易的最后记录日。
我喜欢的显示结果应该是这样的:
+------+-------+--------+
| Year | Month | Amount |
+------+-------+--------+
| 2019 | 01 | 40 |
| 2019 | 02 | 60 |
| 2019 | 03 | 80 |
+------+-------+--------+
对于 Year
和 Month
的每个组合,您想获得最大的 Day
和 Amount
值:
SELECT Year, Month, max(Day) as Day, max(Amount) as Amount
FROM t
GROUP BY Year, Month;
请注意,出现在 SELECT
子句中但未出现在 GROUP BY
子句中的每一列都必须聚合(此处为 max
)。
也就是说,假设 Amount
对应于每天的总数,这就是您的示例所建议的。
如果您的 table 每天包含超过一个 Amount
,那么您还需要总结每天的金额。我会使用类似的东西:
SELECT Year, Month, max(Day) as Day, max(Amount) as Amount
FROM (
SELECT Year, Month, Day, sum(Amount) as Amount
FROM t
GROUP BY Year, Month, Day
) as tmp
GROUP BY Year, Month;
test me(在您的示例中再添加一笔金额)
或:
SELECT Year, Month, Day, sum(Amount) as Amount
FROM (
SELECT *, rank() over(partition by Year, Month order by Day desc) as r
FROM t
) as tmp
WHERE r = 1
GROUP BY Year, Month, Day;
请注意,您要在此处使用 rank()
而不是 row_number()
,因为您需要为领带(同一天)提供相同的排名标识符。
当然,如果你愿意,你可以将上面的任何查询包装成:
SELECT Year, Month, Amount
FROM (<query>) as q;
删除日期栏。
您可以使用行号来实现:
SELECT [Year], [Month], [Amount]
FROM (
SELECT ROW_NUMBER() OVER(PARTITION BY CONCAT(YEAR,MONTH) ORDER BY DAY DESC) rn, *
FROM table) t
WHERE rn = 1
一种方法是相关子查询:
select t.*
from t
where t.day = (select max(t2.day)
from t t2
where t2.year = t.year and t2.month = t.month
);
另一种常用方法使用 row_number()
:
select t.*
from (select t.*,
row_number() over (partition by year, month order by day desc) as seqnum
from t
) t
where seqnum = 1;
select year,month,amount from(SELECT year,month,max(day),amount FROM t GROUP BY year,month);
您可以在下方使用:
SELECT ROW_NUMBER() OVER(PARTITION BY YEAR, MONTH ORDER BY DAY DESC) as rn, * FROM yourtable QUALIFY rn = 1
使用 ROW_NUMBER() 函数:
with cte_order as (select year, month, amount,row_number() over(partition by month order by day desc) as identity_row from test1)
select 年、月、金额 cte_order 其中 identity_row = 1;
使用 QUALIFY() 函数:
select year, month, amount, day, row_number() over(partition by month order by day desc) as identity_row from test1 qualify identity_row = 1;