我的软件在几个数据库上运行,所以我需要通用(显然,我认为“独特的”解决方案可能有效,但这不是标准的。)
假设我有两个表定义为:
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行。单个查询是否可以这样?
答案 0 :(得分: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小提琴:http://sqlfiddle.com/#!3/9de72/1
答案 1 :(得分: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之类的查询。但这些功能会使查询对某些平台更具限制性。