SQL 查询给定的 select 操作
SQL query for the given select operation
考虑一个 table T,有列
- ID = 例如客户 ID
- 费用 = 购买商品所花费的金额
- 日期=交易日期
- 物品 = 购买的物品
我想在 T 上执行以下 select 操作。
我想为每个 ID 查找最早购买的最昂贵的商品。
例如table有如下3条记录
ID Expense Date item
1 1000 10/20/2015 A
1 1000 10/21/2015 B
1 200 10/15/2015 C
它应该选择第一行。
我写了类似下面的东西,但它似乎不起作用
select T.id. T.expense, T.date, T.item
from T inner join
(select id, max(expense), min(date) from T
group by id) w on T.id = w.id and T.expense=w.expense and T.date=w.date;
请给点建议。
谢谢
尝试:
Select * from
(select row_number() over (partition by ID order by Expense desc, date asc)
RN, id, expense, date, item
from T)T
where RN=1
编辑:这个答案是错误的,因为这个问题最初被标记错了。我会编辑,但这里已经有另一个正确答案。我把它留在这里是因为它仍然展示了一个可行的解决方案,甚至适用于 MySql,但你真的应该投票给 row_number()
解决方案。
考虑分三步完成此操作。首先,您需要找出最大费用是多少。然后你需要找到相应的最小日期。最后,您可以获得与这些值匹配的整个记录。如果一个 ID 可能有多个记录同时匹配最大值和最小值,您将需要一个额外的步骤来将其归结为单个记录。
这些步骤中的每一个都可以通过子查询上的 JOIN 来完成:
select .*
FROM T tf --final
INNER JOIN (
select Td.ID, Td.expense, MIN(Td.date) MinDate
from T td --date
INNER JOIN (
select ID, MAX(expense) MaxExpense
from T te --expense
GROUP BY ID
) e on td.ID = e.ID AND td.expense = e.MaxExpense
GROUP BY ID, expense
) d ON tf.ID = d.ID AND tf.expense = d.expense AND tf.date = d.MinDate
同样,使用支持 Window 函数或 APPLY 运算符的数据库引擎,这要简单得多。这是您可以使用 Sql Server:
编写的应用示例
SELECT t1.*
FROM T t1
CROSS APPLY (
SELECT TOP 1 *
FROM T t2
WHERE t2.ID = t1.ID
ORDER BY t2.expense DESC, t1.Date
) a
此功能受 Sql Server、Oracle 和 Postgresql 支持,并且成为 ANSI 标准的一部分已有 10 多年的历史,这只是 MySql 的几个原因之一在实际使用过一种以上数据库的人中间很快成为一个笑话。
在 oracle、DB2 或 MS SQL 中,您可以这样做以获得每一行的项目:
select T.id. T.expense, T.date, T.item,
max(T.expense) OVER (partition by T.id order by T.date asc) as m_expense
from T
并以此获取符合这些条件的项目
SELECT id, expense, date, item
FROM (
select T.id, T.expense, T.date, T.item,
ROW_NUMBER() OVER (partition by T.id order by T.expense DESC, T.date asc) as rn
from T
) x
WHERE rn = 1
这利用了 windowing 函数之一。解释什么是 windowing 函数的最好方法是说它们完全满足您的需求:将函数应用于行的子集(window)。
这应该有效
select t.id, t.expense, min(t.date), t.item
from (select max(expense) as expense, id from T group by id) x
join t
on t.id = x.id and t.expense = x.expense
group by t.id
考虑一个 table T,有列
- ID = 例如客户 ID
- 费用 = 购买商品所花费的金额
- 日期=交易日期
- 物品 = 购买的物品
我想在 T 上执行以下 select 操作。
我想为每个 ID 查找最早购买的最昂贵的商品。
例如table有如下3条记录
ID Expense Date item
1 1000 10/20/2015 A
1 1000 10/21/2015 B
1 200 10/15/2015 C
它应该选择第一行。
我写了类似下面的东西,但它似乎不起作用
select T.id. T.expense, T.date, T.item
from T inner join
(select id, max(expense), min(date) from T
group by id) w on T.id = w.id and T.expense=w.expense and T.date=w.date;
请给点建议。 谢谢
尝试:
Select * from
(select row_number() over (partition by ID order by Expense desc, date asc)
RN, id, expense, date, item
from T)T
where RN=1
编辑:这个答案是错误的,因为这个问题最初被标记错了。我会编辑,但这里已经有另一个正确答案。我把它留在这里是因为它仍然展示了一个可行的解决方案,甚至适用于 MySql,但你真的应该投票给 row_number()
解决方案。
考虑分三步完成此操作。首先,您需要找出最大费用是多少。然后你需要找到相应的最小日期。最后,您可以获得与这些值匹配的整个记录。如果一个 ID 可能有多个记录同时匹配最大值和最小值,您将需要一个额外的步骤来将其归结为单个记录。
这些步骤中的每一个都可以通过子查询上的 JOIN 来完成:
select .*
FROM T tf --final
INNER JOIN (
select Td.ID, Td.expense, MIN(Td.date) MinDate
from T td --date
INNER JOIN (
select ID, MAX(expense) MaxExpense
from T te --expense
GROUP BY ID
) e on td.ID = e.ID AND td.expense = e.MaxExpense
GROUP BY ID, expense
) d ON tf.ID = d.ID AND tf.expense = d.expense AND tf.date = d.MinDate
同样,使用支持 Window 函数或 APPLY 运算符的数据库引擎,这要简单得多。这是您可以使用 Sql Server:
编写的应用示例SELECT t1.*
FROM T t1
CROSS APPLY (
SELECT TOP 1 *
FROM T t2
WHERE t2.ID = t1.ID
ORDER BY t2.expense DESC, t1.Date
) a
此功能受 Sql Server、Oracle 和 Postgresql 支持,并且成为 ANSI 标准的一部分已有 10 多年的历史,这只是 MySql 的几个原因之一在实际使用过一种以上数据库的人中间很快成为一个笑话。
在 oracle、DB2 或 MS SQL 中,您可以这样做以获得每一行的项目:
select T.id. T.expense, T.date, T.item,
max(T.expense) OVER (partition by T.id order by T.date asc) as m_expense
from T
并以此获取符合这些条件的项目
SELECT id, expense, date, item
FROM (
select T.id, T.expense, T.date, T.item,
ROW_NUMBER() OVER (partition by T.id order by T.expense DESC, T.date asc) as rn
from T
) x
WHERE rn = 1
这利用了 windowing 函数之一。解释什么是 windowing 函数的最好方法是说它们完全满足您的需求:将函数应用于行的子集(window)。
这应该有效
select t.id, t.expense, min(t.date), t.item
from (select max(expense) as expense, id from T group by id) x
join t
on t.id = x.id and t.expense = x.expense
group by t.id