2017-09-12 39 views
1

我有两个表 - 测试,包含版本化数据的子表。 说明有关列:SQL优化内部连接(使用内部连接并可能使用子查询)

TEST, CHILD Table 
ID - Record id (not unique due to multiple versions) 
MODSTAMP - Timestamp at which record is inserted 
DELETEDDATE - Timestamp at which record is deleted; NULL value means record is not deleted yet. 
COMPOSITE KEY = {ID, MODSTAMP} 

CHILD Table 
DATA - Foreign key that references Test(ID) 
DATA2 - Foreign key that references Test(ID) 

我的工作,其中记录两个时间戳之间选择的需求 - $ FROMTIME和$ TOTIME。我可以通过运行自联接来选择Test表上的记录。

SELECT v.id, v.modstamp FROM test v 
INNER JOIN 
    (SELECT Id, MAX(modstamp) AS MaxDateTime 
    FROM test where modstamp >= '2017-08-16 15:08:04 +00:00' and modstamp <= '2017-08-16 17:08:04 +00:00' GROUP BY Id) g 
ON v.Id = g.Id 
AND v.modstamp = g.MaxDateTime where v.deleteddate is null 

我还需要选择最新版本的相应的子记录(没有任何重复的记录ID,因此group by子句)父记录被选择哪个。我的应用程序拥有上面的查询结果,并运行下面的查询来选择有效的子记录的每一个值[“AAA”,“BBB”]:

SELECT v.* FROM child v 
    INNER JOIN 
     (SELECT id, MAX(modstamp) AS MaxDateTime 
     FROM child where (data = ? or data is null) and modstamp <= '2017-08-16 17:08:04 +00:00' GROUP BY id 
      UNION 
     SELECT id, MAX(modstamp) AS MaxDateTime 
     FROM child where (data2 = ? or data2 is null) and modstamp <= '2017-08-16 17:08:04 +00:00' GROUP BY id 
     ) g 
    ON v.id = g.id 
    AND v.modstamp = g.MaxDateTime 

任何人都可以建议如何优化这个解决方案?使用当前的方法,如果选择了n个父记录,则会有n个将要运行的内部连接。

这是用于连接的查询,但会抛出'未找到多部分标识符错误'。任何其他方式来重写查询? (使用SQL Server)

Test 
| ID | MODSTAMP | DELETEDDATE | 

Child 
| ID | DATA | DATA2 | MODSTAMP | DELETEDDATE | 

脚本: - 意查询

SELECT v.* FROM child v 
    INNER JOIN (select distinct(id) from DATA) D 
    ON v.id = D.id 
    INNER JOIN 
     (SELECT id, MAX(modstamp) AS MaxDateTime 
     FROM child where (data = d.id or data is null) and modstamp <= '2017-08-16 17:08:04 +00:00' GROUP BY id 
      UNION 
     SELECT id, MAX(modstamp) AS MaxDateTime 
     FROM child where (data2 = d.id or data2 is null) and modstamp <= '2017-08-16 17:08:04 +00:00' GROUP BY id 
     ) g 
    ON v.id = g.id 
    AND v.modstamp = g.MaxDateTime; 

样品信息来运行该脚本

drop table test; 
drop table child; 

CREATE TABLE TEST(ID VARCHAR(20), modstamp DATETIMEOFFSET, deleteddate DATETIMEOFFSET); 
insert into test values('aaa', '2017-08-16 15:08:04 +00:00', null); 
insert into test values('aaa', '2017-08-16 16:08:04 +00:00', null); 
insert into test values('aaa', '2017-08-16 17:08:04 +00:00', null); 
insert into test values('aaa', '2017-08-16 18:08:04 +00:00', '2017-08-16 18:08:04 +00:00'); 
insert into test values('bbb', '2017-08-16 17:08:04 +00:00', null); 

CREATE TABLE CHILD(ID VARCHAR(20), DATA VARCHAR(10), DATA2 VARCHAR(10), modstamp DATETIMEOFFSET, deleteddate DATETIMEOFFSET); 
insert into CHILD values('1', 'aaa', null, '2017-08-16 15:08:04 +00:00', null); 
insert into CHILD values('1', null, 'bbb', '2017-08-16 16:08:04 +00:00', null); 
insert into CHILD values('1', null, null, '2017-08-16 17:08:04 +00:00', null); 
insert into CHILD values('2', 'aaa', null, '2017-08-16 15:08:04 +00:00', null); 
insert into CHILD values('3', null, null, '2017-08-16 15:08:04 +00:00', null); 
+0

您是否正在寻找更短的写法?我不明白这个问题。 – SQLChao

+0

是的。我正在寻找优化父记录ID列表('aaa','bbb')的子记录选择。 – dmachop

+0

row_number将比最大聚合更快。 – scsimon

回答

0

你的查询看起来不错。我不会调用以下查询优化,但另一种方法是使用ROW_NUMBER()

SELECT * FROM (
SELECT *, rownum = ROW_NUMBER() OVER (PARTITION BY id ORDER BY modstamp) 
FROM child 
WHERE (data = ? OR data IS NULL OR data2 = ? OR data2 IS NULL) AND modstamp <= '2017-08-16 17:08:04 +00:00' 
) AS a where rownum = 1