Sql 仅选择具有上次修改的时间戳的行,不选择具有相同ID和较旧时间戳的重复行
我找不到解决问题的办法。我有两张表Order和OrderDetail 订单表(简单版)Sql 仅选择具有上次修改的时间戳的行,不选择具有相同ID和较旧时间戳的重复行,sql,firebird,Sql,Firebird,我找不到解决问题的办法。我有两张表Order和OrderDetail 订单表(简单版) 订单详细信息(简单版) 如何从OrderDetails表中获取与Order表中上次修改的时间戳相连接的行 结果应该是: | order_id | detail_id | base_price | buy_price | sell_price | modified | | 5 | 1 | 92.00 | 106.00 | 116.00 | 25.1.201
订单详细信息(简单版)
如何从OrderDetails表中获取与Order表中上次修改的时间戳相连接的行 结果应该是:
| order_id | detail_id | base_price | buy_price | sell_price | modified |
| 5 | 1 | 92.00 | 106.00 | 116.00 | 25.1.2018.|
| 4 | 2 | 92.00 | 106.00 | 116.00 | 20.1.2018.|
| 5 | 3 | 82.00 | 95.00 | 117.00 | 25.1.2018.|
| 3 | 4 | 90.00 | 100.00 | 120.00 | 15.1.2018.|
| 5 | 5 | 90.00 | 100.00 | 120.00 | 25.1.2018.|
我知道如何联接表,以及如何从具有所需列的联接表中获取所有行,但我不知道如何仅从每个订单id、细节id对中筛选具有最新时间戳的行。求求你,任何帮助都将不胜感激
编辑
需要对Firebird数据库进行查询
编辑2。
第一个样本数据有点误导。请再次查看扩展表和期望的结果。
我需要所有不同的行(基于“details_id”)和它最后修改的数据。如何为每个具有较旧时间戳的“详细信息id”排除“重复”行,并仅保留具有最新时间戳的“详细信息id”行???您可以尝试此查询。根据修改后的日期从订单表中获取最顶层的行,然后将该行与orderdetails表内部联接
SELECT od.*, o.modified
FROM OrderDetails od
Inner join (Select top 1 * -- get topmost row
from [Order]
order by modified desc ) O on o.id = od.order_id
您可以尝试此查询。根据修改后的日期从订单表中获取最顶层的行,然后将该行与orderdetails表内部联接
SELECT od.*, o.modified
FROM OrderDetails od
Inner join (Select top 1 * -- get topmost row
from [Order]
order by modified desc ) O on o.id = od.order_id
这涉及问题的前两个版本 对于每个详细信息记录,您需要最新的
订单
记录。随着数据的排列,这相当于最大的订单id
。使用该日期比使用日期更简单:
select od.*
from orderdetail od
where od.order_id = (select max(od2.order_id)
from orderdetail od2
where od2.detail_id = od.detail_id
);
这涉及问题的前两个版本 对于每个详细信息记录,您需要最新的
订单
记录。随着数据的排列,这相当于最大的订单id
。使用该日期比使用日期更简单:
select od.*
from orderdetail od
where od.order_id = (select max(od2.order_id)
from orderdetail od2
where od2.detail_id = od.detail_id
);
这里我们使用公共的表表达式,所以我们只连接两个表一次。
至少我们在编写查询时只做了一次,这样我们就不会有太多的机会出现打字错误或复制粘贴错误。
我们还提示SQL server只执行一次连接,然后再重新使用它,但它是否遵循此提示—取决于其内部实现
CTE的另一个优点是:它可以帮助您逐步地从简单到复杂地增量构建查询。在稍后我会再补充一点 你可以在谷歌上找到很多关于CTE的文章。Firebird的实施记录如下: 因为我只使用了非常基本的SQL,所以我相信它几乎可以在任何实际的SQL server中工作,包括Firebird 以下是查询结果和输出数据: PostgreSQL 9.6架构设置:
create table orders
(id integer primary key,
modified timestamp);
create index o_m on orders(modified);
create table OrderDetails(
order_id integer references orders(id),
detail_id integer not null,
base_price float,
buy_price float,
sell_price float );
create index od_do on OrderDetails(detail_id, order_id);
Insert into orders values
( 1, '2018-1-07'),
( 2, '2018-1-10'),
( 3, '2018-1-15'),
( 4, '2018-1-20'),
( 5, '2018-1-25');
Insert into OrderDetails values
( 1 , 1 , 99.00 , 111.00 , 122.00 ),
( 1 , 2 , 82.00 , 95.00 , 117.00 ),
( 1 , 3 , 82.00 , 95.00 , 117.00 ),
( 2 , 4 , 95.00 , 108.00 , 119.00 ),
( 2 , 5 , 86.00 , 94.00 , 115.00 ),
( 2 , 1 , 82.00 , 95.00 , 117.00 ),
( 3 , 1 , 92.00 , 106.00 , 116.00 ),
( 3 , 4 , 90.00 , 100.00 , 120.00 ),
( 3 , 5 , 82.00 , 95.00 , 117.00 ),
( 4 , 2 , 92.00 , 106.00 , 116.00 ),
( 4 , 3 , 90.00 , 100.00 , 120.00 ),
( 4 , 1 , 82.00 , 95.00 , 117.00 ),
( 5 , 1 , 92.00 , 106.00 , 116.00 ),
( 5 , 5 , 90.00 , 100.00 , 120.00 ),
( 5 , 3 , 82.00 , 95.00 , 117.00 );
with x as (select o.modified, od.*
from orderDetails od, orders o
where o.id=od.order_id)
, mx as (select max(modified) as modified, detail_id
from x group by detail_id)
Select x.* from x, mx
Where x.detail_id = mx.detail_id and x.modified=mx.modified
Order by detail_id
| modified | order_id | detail_id | base_price | buy_price | sell_price |
|----------------------|----------|-----------|------------|-----------|------------|
| 2018-01-25T00:00:00Z | 5 | 1 | 92 | 106 | 116 |
| 2018-01-20T00:00:00Z | 4 | 2 | 92 | 106 | 116 |
| 2018-01-25T00:00:00Z | 5 | 3 | 82 | 95 | 117 |
| 2018-01-15T00:00:00Z | 3 | 4 | 90 | 100 | 120 |
| 2018-01-25T00:00:00Z | 5 | 5 | 90 | 100 | 120 |
查询1:
create table orders
(id integer primary key,
modified timestamp);
create index o_m on orders(modified);
create table OrderDetails(
order_id integer references orders(id),
detail_id integer not null,
base_price float,
buy_price float,
sell_price float );
create index od_do on OrderDetails(detail_id, order_id);
Insert into orders values
( 1, '2018-1-07'),
( 2, '2018-1-10'),
( 3, '2018-1-15'),
( 4, '2018-1-20'),
( 5, '2018-1-25');
Insert into OrderDetails values
( 1 , 1 , 99.00 , 111.00 , 122.00 ),
( 1 , 2 , 82.00 , 95.00 , 117.00 ),
( 1 , 3 , 82.00 , 95.00 , 117.00 ),
( 2 , 4 , 95.00 , 108.00 , 119.00 ),
( 2 , 5 , 86.00 , 94.00 , 115.00 ),
( 2 , 1 , 82.00 , 95.00 , 117.00 ),
( 3 , 1 , 92.00 , 106.00 , 116.00 ),
( 3 , 4 , 90.00 , 100.00 , 120.00 ),
( 3 , 5 , 82.00 , 95.00 , 117.00 ),
( 4 , 2 , 92.00 , 106.00 , 116.00 ),
( 4 , 3 , 90.00 , 100.00 , 120.00 ),
( 4 , 1 , 82.00 , 95.00 , 117.00 ),
( 5 , 1 , 92.00 , 106.00 , 116.00 ),
( 5 , 5 , 90.00 , 100.00 , 120.00 ),
( 5 , 3 , 82.00 , 95.00 , 117.00 );
with x as (select o.modified, od.*
from orderDetails od, orders o
where o.id=od.order_id)
, mx as (select max(modified) as modified, detail_id
from x group by detail_id)
Select x.* from x, mx
Where x.detail_id = mx.detail_id and x.modified=mx.modified
Order by detail_id
| modified | order_id | detail_id | base_price | buy_price | sell_price |
|----------------------|----------|-----------|------------|-----------|------------|
| 2018-01-25T00:00:00Z | 5 | 1 | 92 | 106 | 116 |
| 2018-01-20T00:00:00Z | 4 | 2 | 92 | 106 | 116 |
| 2018-01-25T00:00:00Z | 5 | 3 | 82 | 95 | 117 |
| 2018-01-15T00:00:00Z | 3 | 4 | 90 | 100 | 120 |
| 2018-01-25T00:00:00Z | 5 | 5 | 90 | 100 | 120 |
:
create table orders
(id integer primary key,
modified timestamp);
create index o_m on orders(modified);
create table OrderDetails(
order_id integer references orders(id),
detail_id integer not null,
base_price float,
buy_price float,
sell_price float );
create index od_do on OrderDetails(detail_id, order_id);
Insert into orders values
( 1, '2018-1-07'),
( 2, '2018-1-10'),
( 3, '2018-1-15'),
( 4, '2018-1-20'),
( 5, '2018-1-25');
Insert into OrderDetails values
( 1 , 1 , 99.00 , 111.00 , 122.00 ),
( 1 , 2 , 82.00 , 95.00 , 117.00 ),
( 1 , 3 , 82.00 , 95.00 , 117.00 ),
( 2 , 4 , 95.00 , 108.00 , 119.00 ),
( 2 , 5 , 86.00 , 94.00 , 115.00 ),
( 2 , 1 , 82.00 , 95.00 , 117.00 ),
( 3 , 1 , 92.00 , 106.00 , 116.00 ),
( 3 , 4 , 90.00 , 100.00 , 120.00 ),
( 3 , 5 , 82.00 , 95.00 , 117.00 ),
( 4 , 2 , 92.00 , 106.00 , 116.00 ),
( 4 , 3 , 90.00 , 100.00 , 120.00 ),
( 4 , 1 , 82.00 , 95.00 , 117.00 ),
( 5 , 1 , 92.00 , 106.00 , 116.00 ),
( 5 , 5 , 90.00 , 100.00 , 120.00 ),
( 5 , 3 , 82.00 , 95.00 , 117.00 );
with x as (select o.modified, od.*
from orderDetails od, orders o
where o.id=od.order_id)
, mx as (select max(modified) as modified, detail_id
from x group by detail_id)
Select x.* from x, mx
Where x.detail_id = mx.detail_id and x.modified=mx.modified
Order by detail_id
| modified | order_id | detail_id | base_price | buy_price | sell_price |
|----------------------|----------|-----------|------------|-----------|------------|
| 2018-01-25T00:00:00Z | 5 | 1 | 92 | 106 | 116 |
| 2018-01-20T00:00:00Z | 4 | 2 | 92 | 106 | 116 |
| 2018-01-25T00:00:00Z | 5 | 3 | 82 | 95 | 117 |
| 2018-01-15T00:00:00Z | 3 | 4 | 90 | 100 | 120 |
| 2018-01-25T00:00:00Z | 5 | 5 | 90 | 100 | 120 |
注意,如果您有两个或更多具有相同时间戳的订单,那么它将有不同的输出!看起来你甚至没有考虑过这种可能性——但既然它是可能的,它最终会发生
现在,返回CTE并回复
当您以增量方式构建查询时,从第一个模糊的概念到特定的行,最好检查输出数据是否正是您所期望的。“大象最好被小块吃掉”
在这里,我将向您展示逐步构建查询的过程。
如果您在上面链接的SQL FIDLE中重复这些步骤,这将非常有用
首先,我创建并填充了表
然后我发出了第一个查询,只是为了检查我是否正确地填充了它们
1:select*from orders
-在SQL FIDLE(或在IBMExpert、FlameRobin等)中尝试此查询和进一步查询
2:从订单详细信息中选择*
3:然后我发出了连接查询来检查我的跨表查询是否真的提供了有意义的输出。它确实提供了
select o.modified, od.*
from orderDetails od, orders o
where o.id=od.order_id
4:然后我想知道,我能从该查询中获取详细信息的最后一个时间戳吗?为了检查它,我做了如下操作:1)保存了前面我做过并测试过的查询,2)在上面编写了一个二次查询。最后一次换衣服的日期确定了。书面和测试
with x as (select o.modified, od.*
from orderDetails od, orders o
where o.id=od.order_id)
Select max(modified) as modified, detail_id
from x group by detail_id
5:最后一步是保存测试二级查询,并在二级查询之上编写最终的三级查询,给出最终的过滤数据
然而,更有效的解决方案是使用一次运行连接查询(我在上面的步骤3中介绍的,并保存为
x
),通过添加order by detail\u id,修改desc
,然后使用Firebird 3中介绍的窗口函数
以下是使用该方法对类似问题的答案-
不过Firebird 2.x中没有窗口功能
这里我们使用公共的表表达式,所以我们只连接两个表一次。
至少我们在编写查询时只做了一次,这样我们就不会有太多的机会出现打字错误或复制粘贴错误。
我们还提示SQL server只执行一次连接,然后再重新使用它,但它是否遵循此提示—取决于其内部实现
CTE的另一个优点是:它可以帮助您逐步地从简单到复杂地增量构建查询。在稍后我会再补充一点 你可以在谷歌上找到很多关于CTE的文章。Firebird的实施记录如下: 因为我只使用了非常基本的SQL,所以我相信它几乎可以在任何实际的SQL server中工作,包括Firebird 以下是查询结果和输出数据: PostgreSQL 9.6架构设置:
create table orders
(id integer primary key,
modified timestamp);
create index o_m on orders(modified);
create table OrderDetails(
order_id integer references orders(id),
detail_id integer not null,
base_price float,
buy_price float,
sell_price float );
create index od_do on OrderDetails(detail_id, order_id);
Insert into orders values
( 1, '2018-1-07'),
( 2, '2018-1-10'),
( 3, '2018-1-15'),
( 4, '2018-1-20'),
( 5, '2018-1-25');
Insert into OrderDetails values
( 1 , 1 , 99.00 , 111.00 , 122.00 ),
( 1 , 2 , 82.00 , 95.00 , 117.00 ),
( 1 , 3 , 82.00 , 95.00 , 117.00 ),
( 2 , 4 , 95.00 , 108.00 , 119.00 ),
( 2 , 5 , 86.00 , 94.00 , 115.00 ),
( 2 , 1 , 82.00 , 95.00 , 117.00 ),
( 3 , 1 , 92.00 , 106.00 , 116.00 ),
( 3 , 4 , 90.00 , 100.00 , 120.00 ),
( 3 , 5 , 82.00 , 95.00 , 117.00 ),
( 4 , 2 , 92.00 , 106.00 , 116.00 ),
( 4 , 3 , 90.00 , 100.00 , 120.00 ),
( 4 , 1 , 82.00 , 95.00 , 117.00 ),
( 5 , 1 , 92.00 , 106.00 , 116.00 ),
( 5 , 5 , 90.00 , 100.00 , 120.00 ),
( 5 , 3 , 82.00 , 95.00 , 117.00 );
with x as (select o.modified, od.*
from orderDetails od, orders o
where o.id=od.order_id)
, mx as (select max(modified) as modified, detail_id
from x group by detail_id)
Select x.* from x, mx
Where x.detail_id = mx.detail_id and x.modified=mx.modified
Order by detail_id
| modified | order_id | detail_id | base_price | buy_price | sell_price |
|----------------------|----------|-----------|------------|-----------|------------|
| 2018-01-25T00:00:00Z | 5 | 1 | 92 | 106 | 116 |
| 2018-01-20T00:00:00Z | 4 | 2 | 92 | 106 | 116 |
| 2018-01-25T00:00:00Z | 5 | 3 | 82 | 95 | 117 |
| 2018-01-15T00:00:00Z | 3 | 4 | 90 | 100 | 120 |
| 2018-01-25T00:00:00Z | 5 | 5 | 90 | 100 | 120 |
查询1:
create table orders
(id integer primary key,
modified timestamp);
create index o_m on orders(modified);
create table OrderDetails(
order_id integer references orders(id),
detail_id integer not null,
base_price float,
buy_price float,
sell_price float );
create index od_do on OrderDetails(detail_id, order_id);
Insert into orders values
( 1, '2018-1-07'),
( 2, '2018-1-10'),
( 3, '2018-1-15'),
( 4, '2018-1-20'),
( 5, '2018-1-25');
Insert into OrderDetails values
( 1 , 1 , 99.00 , 111.00 , 122.00 ),
( 1 , 2 , 82.00 , 95.00 , 117.00 ),
( 1 , 3 , 82.00 , 95.00 , 117.00 ),
( 2 , 4 , 95.00 , 108.00 , 119.00 ),
( 2 , 5 , 86.00 , 94.00 , 115.00 ),
( 2 , 1 , 82.00 , 95.00 , 117.00 ),
( 3 , 1 , 92.00 , 106.00 , 116.00 ),
( 3 , 4 , 90.00 , 100.00 , 120.00 ),
( 3 , 5 , 82.00 , 95.00 , 117.00 ),
( 4 , 2 , 92.00 , 106.00 , 116.00 ),
( 4 , 3 , 90.00 , 100.00 , 120.00 ),
( 4 , 1 , 82.00 , 95.00 , 117.00 ),
( 5 , 1 , 92.00 , 106.00 , 116.00 ),
( 5 , 5 , 90.00 , 100.00 , 120.00 ),
( 5 , 3 , 82.00 , 95.00 , 117.00 );
with x as (select o.modified, od.*
from orderDetails od, orders o
where o.id=od.order_id)
, mx as (select max(modified) as modified, detail_id
from x group by detail_id)
Select x.* from x, mx
Where x.detail_id = mx.detail_id and x.modified=mx.modified
Order by detail_id
| modified | order_id | detail_id | base_price | buy_price | sell_price |
|----------------------|----------|-----------|------------|-----------|------------|
| 2018-01-25T00:00:00Z | 5 | 1 | 92 | 106 | 116 |
| 2018-01-20T00:00:00Z | 4 | 2 | 92 | 106 | 116 |
| 2018-01-25T00:00:00Z | 5 | 3 | 82 | 95 | 117 |
| 2018-01-15T00:00:00Z | 3 | 4 | 90 | 100 | 120 |
| 2018-01-25T00:00:00Z | 5 | 5 | 90 | 100 | 120 |
:
create table orders
(id integer primary key,
modified timestamp);
create index o_m on orders(modified);
create table OrderDetails(
order_id integer references orders(id),
detail_id integer not null,
base_price float,
buy_price float,
sell_price float );
create index od_do on OrderDetails(detail_id, order_id);
Insert into orders values
( 1, '2018-1-07'),
( 2, '2018-1-10'),
( 3, '2018-1-15'),
( 4, '2018-1-20'),
( 5, '2018-1-25');
Insert into OrderDetails values
( 1 , 1 , 99.00 , 111.00 , 122.00 ),
( 1 , 2 , 82.00 , 95.00 , 117.00 ),
( 1 , 3 , 82.00 , 95.00 , 117.00 ),
( 2 , 4 , 95.00 , 108.00 , 119.00 ),
( 2 , 5 , 86.00 , 94.00 , 115.00 ),
( 2 , 1 , 82.00 , 95.00 , 117.00 ),
( 3 , 1 , 92.00 , 106.00 , 116.00 ),
( 3 , 4 , 90.00 , 100.00 , 120.00 ),
( 3 , 5 , 82.00 , 95.00 , 117.00 ),
( 4 , 2 , 92.00 , 106.00 , 116.00 ),
( 4 , 3 , 90.00 , 100.00 , 120.00 ),
( 4 , 1 , 82.00 , 95.00 , 117.00 ),
( 5 , 1 , 92.00 , 106.00 , 116.00 ),
( 5 , 5 , 90.00 , 100.00 , 120.00 ),
( 5 , 3 , 82.00 , 95.00 , 117.00 );
with x as (select o.modified, od.*
from orderDetails od, orders o
where o.id=od.order_id)
, mx as (select max(modified) as modified, detail_id
from x group by detail_id)
Select x.* from x, mx
Where x.detail_id = mx.detail_id and x.modified=mx.modified
Order by detail_id
| modified | order_id | detail_id | base_price | buy_price | sell_price |
|----------------------|----------|-----------|------------|-----------|------------|
| 2018-01-25T00:00:00Z | 5 | 1 | 92 | 106 | 116 |
| 2018-01-20T00:00:00Z | 4 | 2 | 92 | 106 | 116 |
| 2018-01-25T00:00:00Z | 5 | 3 | 82 | 95 | 117 |
| 2018-01-15T00:00:00Z | 3 | 4 | 90 | 100 | 120 |
| 2018-01-25T00:00:00Z | 5 | 5 | 90 | 100 | 120 |
注意,如果您有两个或更多具有相同时间戳的订单,那么它将有不同的输出!看起来你甚至没有考虑过这种可能性——但既然它是可能的,那它就不可能了