这是我的SQL查询,我得到了所有重复项,但是一个(最新的):
SELECT d.C_ContactID, d.C_EmailAddress, d.C_DataSourceID, d.C_DateCreated
FROM duplicates as d
WHERE d.C_DateCreated !=(select max(d2.C_DateCreated)
FROM duplicates d2
WHERE d2.C_DataSourceId = d.C_DataSourceId)
有可能以某种方式优化它吗?不幸的是,在30万条记录中需要花费+ - 40分钟。
查询的方法是:
public ArrayList<Record> get() throws SQLException,
ClassNotFoundException {
Statement st = DBConnect.DBC.con.createStatement();
String sql = ("select d.C_ContactID, d.C_EmailAddress, d.C_DataSourceID,
d.C_DateCreated "
+ "from duplicates as d "
+ "where d.C_DateCreated !=(select max(d2.C_DateCreated) "
+ "from duplicates d2 where d2.C_DataSourceId = d.C_DataSourceId)");
ResultSet rs = st.executeQuery(sql);
DBConnect.DBC.con.commit();
while (rs.next()) {
int contactID = rs.getInt("C_ContactID");
String email = rs.getString("C_EmailAddress");
String dataSourceID = rs.getString("C_DataSourceID");
String dateCreated = rs.getString("C_DateCreated");
duplicate = new Record(contactID, email, dataSourceID, dateCreated);
duplicates.add(duplicate);
}
rs.close();
st.close();
return duplicates;
}
答案 0 :(得分:2)
首先要在duplicates(C_DataSourceId, C_DateCreated)
上创建一个索引:
create index duplicates_DataSourceId_DateCreated on duplicates(C_DataSourceId, C_DateCreated);
如果您使用的是支持窗口函数的数据库,那么我将其改为:
SELECT d.C_ContactID, d.C_EmailAddress, d.C_DataSourceID, d.C_DateCreated
FROM (select d.*, max(C_DateCreated) over (partition by C_DataSourceId) as maxdc
from duplicates d
) d
WHERE d.C_DateCreated <> maxdc;
值得进行比较,因为有时候窗口函数有效实现。
而且,如果您有索引,则查询的效率稍高一点:
SELECT d.C_ContactID, d.C_EmailAddress, d.C_DataSourceID, d.C_DateCreated
FROM duplicates d
WHERE EXISTS (select 1
from duplicates 2
where d2.C_DataSourceId = d.C_DataSourceId and
d2.C_DateCreated > d.C_DateCreated
);
这表示从重复项中获取所有行,其中有另一行(具有相同的源)创建了更大的日期。一个小小的优点是,它不必查看所有值来获取max()
。它只需要找到第一个。主要的性能改进将是综合指数。
答案 1 :(得分:1)
为列C_DateCreated和C_DataSourceId创建索引。这将减少执行查询的时间。请参阅此链接以了解如何创建索引。 http://www.tutorialspoint.com/mysql/mysql-indexes.htm
答案 2 :(得分:0)
在T-SQL中,答案看起来像这样,但我认为SQLite不支持窗口函数(尽管后代的答案完好无损):
你可以使用一个窗口函数用它在公共C_DataSourceIDs组中的位置标记每一行,然后用CTE选择那些不在位置1的行。
with ordered as (
select
d.C_ContactID,
d.C_EmailAddress,
d.C_DataSourceID,
d.C_DateCreated,
row_number() over (
partition by
d.C_DataSourceID
order by
d.C_DateCreated
) as rownum
from
duplicates
) select
C_ContactID,
C_EmailAddress,
C_DataSourceID,
C_DateCreated
from
ordered
where
rownum != 1;
使用(C_DataSourceID, C_DateCreated)
上的索引,只需要对表进行一次传递,而不是查询中的自联接。