【发布时间】:2018-03-10 13:22:32
【问题描述】:
我有 2 个表,transactions 和 identifiers。每个事务都有一个 user_id,每个 user_id 可以有多个标识符,例如
交易
user_id | amount | timestamp
12 10.00 1234567890
17 5.00 1234567890
12 7.00 1234567890
3 2.50 1234567890
标识符
identifier | user_id
AEFT67 12
JHDASJK 12
KJSIDJ6 3
LKSDLK 5
HSDJH8 17
IUSDI5 17
我想得到这样的结果:
结果:
user_id | identifier | amount | timestamp
12 AEFT67 10.00 1234567890
17 HSDJH8 5.00 1234567890
12 AEFT67 7.00 1234567890
3 KJSIDJ6 2.50 1234567890
两个表都有数百万行,重要的是我在使用连接时不会得到重复(否则数量将是错误的)。
我最初尝试过:
SELECT t.user_id, t.amount, i.identifier
FROM transactions AS t
LEFT JOIN identifiers AS i ON i.id = (
SELECT
i2.id
FROM identifiers i2
WHERE i2.user_id = t.user_id
LIMIT 1
)
WHERE t.timestamp BETWEEN 1234567890 AND 1234567890
注意 - 我实际上并不介意我为用户获取哪个标识符,但一个用户可能有很多。尽管在大型数据集上嵌套 JOIN 非常慢(大约 40 秒),但我尝试了:
SELECT t1.user_id, t1.amount, i1.identifier FROM
(SELECT *
FROM transactions as t
WHERE t.timestamp BETWEEN 1234567890 AND 1234567890) as t1
LEFT JOIN
(SELECT * FROM identifiers GROUP BY user_id) i1
ON i1.user_id =t1.user_id
这实际上将时间缩短了一半,但仍然很慢。
我觉得我遗漏了一些明显的东西,在每种情况下,我都在 identifiers 表中搜索大量数据,这会减慢它的速度(数百万行而不是 1000 左右需要)。我觉得如果我能够在第二个查询中使用第一个查询的结果作为参数,它会更快,即:
SELECT * FROM
(SELECT *
FROM transactions
WHERE t.timestamp BETWEEN 1234567890 AND 1234567890) as t1
LEFT JOIN
(SELECT * FROM identifiers WHERE user_id in (t1.user_id))
有没有更好的方法通过引用单个(任何)标识符来获取我的过滤交易?
编辑:这是一个 sql fiddle 设置:http://sqlfiddle.com/#!9/ecad23/6
EDIT2:为了进一步说明,我需要维护每个事务的记录,因此如果 where 查询仅应用于 事务,返回的行数应该正是您所期望的桌子。用户可以有多个事务,因此无法对最终结果进行分组
【问题讨论】:
-
如果我理解正确,您希望为每个用户提取一个标识符。您对如何选择标识符有任何标准(字母顺序、字符串大小)或者是否有任何标准匹配?
-
@dragmosh 标识符不需要任何标准,任何都可以
标签: mysql join query-optimization