2

我的软件在几个数据库上运行,所以我需要通用(值得注意的是,我认为“distinct on”解决方案可能有效,但这不是标准的)。

假设我有两个表定义为:

Table A: id, time (pk: id)
Table B: id(fk), key, value (pk: id, key)

其中表 B 的 id 是表 A 的外键,主键是指定的。

我需要所请求密钥的最新(及时)值。所以,假设我有如下数据:

id | key | value
1  | A   | v1
1  | B   | v2
1  | C   | v3
2  | A   | v4
2  | C   | v5
3  | B   | v6
3  | D   | v7

如果 id 的时间在增加,并且我想要键 A 和 C 的值,我希望得到如下结果:

key | value
A   | v4
C   | v5

或者对于键 D 和 A:

key | value
D   | v7
A   | v4

理想情况下,对于 n 个关键请求,我只会返回 n 行。单个查询可以实现这样的事情吗?

4

2 回答 2

2

这是它与 SQL Server 2008 R2 一起使用的情况:

架构

CREATE TABLE B (
   ind integer,
   [key] varchar(8),
   value varchar(16)
);

INSERT INTO B VALUES (1, 'A', 'v1');
INSERT INTO B VALUES (1, 'B', 'v2');
INSERT INTO B VALUES (1, 'C', 'v3');
INSERT INTO B VALUES (2, 'A', 'v4');
INSERT INTO B VALUES (2, 'C', 'v5');
INSERT INTO B VALUES (3, 'B', 'v6');
INSERT INTO B VALUES (3, 'D', 'v7');
INSERT INTO B VALUES (3, 'A', 'v12');
INSERT INTO B VALUES (3, 'C', 'v17');
INSERT INTO B VALUES (3, 'C', 'v101');

询问

select [key], max(CAST(SUBSTRING(value, 2, LEN(value)) as INT)) from B
where [key] in ('A', 'C')
group by [key]

如果要保留 v 作为前缀,请执行以下操作:

select [key], 'v' + CAST(max(CAST(SUBSTRING(value, 2, LEN(value)) as INT)) as VARCHAR) as Value
from B
where [key] in ('A', 'C')
group by [key]

输出

| KEY |    VALUE |
------------------
|   A |      v12 |
|   C |     v101 |

要玩的 SQL Fiddle:http ://sqlfiddle.com/#!3/9de72/1

于 2012-08-24T00:42:37.917 回答
1

我假设没有 ID 值将具有相同的 TIME 值。

我相信以下内容与在尽可能多的数据库上运行的选项一样通用。但是平台灵活性的折衷并没有达到最佳性能。

具有别名 t 的子查询标识每个键可用的最新时间。

select a.id,
       a.time,
       b.key,
       b.value
  from tableB as b
  inner join tableA as a
    on a.id=b.id
  inner join (
      select b2.key,
             max(a2.time) time
        from tableB as b2
       inner join tableA as a2 on a2.id=b2.id
       group by b2.key
  ) as t on a.time = t.time and b.key = t.key
  where b.key in ('D','A')

WHERE 子句可以移动到子查询中,它在具有原始优化器的数据库上可能会稍微好一些。但是将 WHERE 子句放在外部查询中可以更容易维护,并且还可以在没有 WHERE 子句的情况下创建视图。然后可以将 WHERE 子句添加到视图中的选择中。

使用 ROW_NUMBER() 的查询会更有效,甚至更好的是使用 Oracle 的 KEEP LAST 之类的查询。但是这些功能会使查询对某些平台更具限制性。

于 2012-08-24T04:15:01.140 回答