0

我有一个看起来像这样的表:

用户数据点:

id | users_id | data_types_id | value | events_id | time_inserted

data_type_id 映射到一些任意的东西,如“名称”或“地址”或一千种其他数据类型。

因此,对于任何个人用户,我可以在此表中有 N 行。

有数百万行。

直接基于 event_id 从该表中进行选择非常快,并且会生成一长串项目,其中每个用户由一定数量的行表示,每行包含一个数据点。

但是,当我需要提取包含每个用户及其数据的某些子集在单独行中的结果时,我通常使用子选择,现在这个过程逐渐放缓。

我的查询看起来(大约)是这样的:

select users_id as uid,
events_id as eid,
(select `value` from users_data_points where users_id = uid and events_id = eid and data_type_id = 3 limit 1) as 'firstName,
        -- ... however many more of these subselects I need here
        from users_data_points where events_id = 500 and date(time_inserted) between '2013-01-01' and date(now())

我完全愿意接受任何可以以更有效的方式产生这种结果的替代解决方案。在生产中,我实际上只是抓取原始行,然后在 Node.js 中将它们哈希映射到一起。这比 SQL 中的子选择快几个数量级,但如果有更好的方法来利用 mySQL 执行此任务,我更愿意不以这种方式拆分工作。

我对临时表或视图或派生表或任何其他可能有效的方法完全开放,但我尝试过的所有内容实际上都比上述解决方案更慢。

4

1 回答 1

0

我完全同意 G-Nugget 的评论。数据库不能很好地格式化数据,但是,仅仅为了它,你可以这样做

select users_id as uid,
events_id as eid,
max(case when data_type = 3 then `value` end) as first_name,
...
from users_data_points 
where events_id = 500 
and date(time_inserted) between '2013-01-01' and date(now())
group by users_id

如果您选择 min() 或 max() 作为聚合函数并不重要。使用case...whens (没有 group by 和聚合函数)你会得到类似的东西

user_id   |   first_name   |   last_name   |   ...
1             john             null            null
1             null             jack            null
1             null             null            whatever

使用 group by 和聚合函数,您可以将它放在一行中,瞧,您拥有没有子查询的枢轴。这应该比您现在的运行速度快几倍,但您仍然可以在应用层上旋转您的数据获得更高的性能。

于 2013-08-02T15:16:01.053 回答