我有2个表可以简化为这种结构:
表1:
+----+----------+---------------------+-------+
| id | descr_id | date | value |
+----+----------+---------------------+-------+
| 1 | 1 | 2013-09-20 16:39:06 | 1 |
+----+----------+---------------------+-------+
| 2 | 2 | 2013-09-20 16:44:06 | 1 |
+----+----------+---------------------+-------+
| 3 | 3 | 2013-09-20 16:49:06 | 5 |
+----+----------+---------------------+-------+
| 4 | 4 | 2013-09-20 16:44:06 | 894 |
+----+----------+---------------------+-------+
表2:
+----------+-------------+
| descr_id | description |
+----------+-------------+
| 1 | abc |
+----------+-------------+
| 2 | abc |
+----------+-------------+
| 3 | abc |
+----------+-------------+
| 4 | DEF |
+----------+-------------+
我想将描述加入到table1中,按描述进行过滤,这样我只得到description = abc的行,并过滤掉“重复”行,如果两行具有相同的值并且它们的日期在6以内,那么这两行是重复的彼此分钟。我想要的输出表在下面,(假设abc是所需的描述过滤器)。
+----+----------+---------------------+-------+-------------+
| id | descr_id | date | value | description |
+----+----------+---------------------+-------+-------------+
| 1 | 1 | 2013-09-20 16:39:06 | 1 | abc |
+----+----------+---------------------+-------+-------------+
| 3 | 3 | 2013-09-20 16:49:06 | 5 | abc |
+----+----------+---------------------+-------+-------------+
我提出的查询是:
select *
from (
select *
from table1
join table2 using(descr_id)
where label='abc'
) t1
left join (
select *
from table1
join table2 using(descr_id)
where label='abc'
) t2 on( t1.date<t2.date and t1.date + interval 6 minute > t2.date)
where t1.value=t2.value.
不幸的是,这个查询花了一分多钟来运行我的数据集,并且没有返回结果(尽管我相信应该有结果)。有更有效的方法来执行此查询吗?有没有办法命名派生表并在以后的同一个查询中引用它?另外,为什么我的查询没有返回任何结果?
提前感谢您的帮助!
编辑: 我想保留几个样本中的第一个具有紧密联系的时间戳。
我的table1有610万行,我的table2有30K,这让我意识到table2只有一行描述“abc”。这意味着我可以事先查询descr_id,然后使用该id来避免在大查询中加入table2,从而提高效率。但是,如果我的table2设置如上所述(这可能是糟糕的数据库设计,我承认)什么是执行此类查询的好方法?
答案 0 :(得分:1)
尝试创建临时表并加入临时表:
CREATE TEMPORARY TABLE t1 AS (select *
FROM table1
JOIN table2 USING(descr_id)
WHERE label='abc')
CREATE TEMPORARY TABLE t2 AS (select *
FROM table1
JOIN table2 USING(descr_id)
WHERE label='abc')
SELECT *
FROM t1
LEFT JOIN t2 on( t1.date<t2.date and t1.date + interval 6 minute > t2.date)
WHERE t1.value=t2.value
从数据库断开连接后会自动清除临时表,因此无需显式删除它们。
我最初有这个,但我不相信它达到了全部要求:
SELECT t1.id,
t1.descr_id,
t1.date,
t1.value,
t2.description
FROM table1 t1
JOIN table2 t2 ON t1.descr_id = t2.descr_id
WHERE t2.description = 'abc'
这与原始查询基本相同,但另一个选项可能是创建视图并在视图上加入,如下所示:
CREATE VIEW v1 AS
SELECT * FROM table1 JOIN table2 USING(descr_id) WHERE label='abc'
CREATE VIEW v2 AS
SELECT * FROM table1 JOIN table2 USING(descr_id) WHERE label='abc'
SELECT *
FROM v1
LEFT JOIN v2 on( v1.date<v2.date and v1.date + interval 6 minute > v2.date)
WHERE v1.value=v2.value
此外,如果您定期运行此查询,您可以考虑将第一个查询的结果加载到临时表中,并在登台表上进行加入,如下所示:
INSERT INTO staging
(SELECT *
FROM table1
JOIN table2 USING(descr_id)
WHERE label='abc')
SELECT *
FROM staging s1
LEFT JOIN staging s2 on( s1.date<s2.date and s1.date + interval 6 minute > s2.date)
WHERE s1.value=s2.value
TRUNCATE TABLE staging
答案 1 :(得分:0)
尝试使用不存在 就像是 选择 * 来自table1 t1 使用(descr_id)连接table2 t2 其中label =&#39; abc&#39;并且不存在(选择* 来自table1 t11 使用(descr_id)连接table2 t22 其中label =&#39; abc&#39;和t1.date&lt; t11.date和t1.date + interval 6分钟&gt; t11.date)
您可能需要仔细检查(t1.date + interval 6分钟)语法