2015-10-20 19 views
0

編輯:檢查不同值的存在,每個組

假設我有在MySQL如下表:

CREATE TABLE `events` (
`pv_name` varchar(60) COLLATE utf8mb4_unicode_ci NOT NULL, 
`time_stamp` bigint(20) UNSIGNED NOT NULL, 
`value` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin, 
PRIMARY KEY (`pv_name`, `time_stamp`) 
) ENGINE=InnoDB; 

我能找到一個具有多個不同的value此表中使用的每個pv_name以下查詢:

SELECT events.pv_name 
FROM events 
GROUP BY events.pv_name 
HAVING COUNT(DISTINCT events.value) > 1; 

問題是此查詢效率不高。它計算所有不同的值,而不是在找到多個值後停止。

一種建議已經執行以下操作:

SELECT events.pv_name 
FROM events 
GROUP BY events.pv_name 
HAVING MIN(events.value) < MAX(events.value); 

這是有效的,如果該索引包括value。但是,value是一個文本列,所以它不能。

是否有另一種方法可以提高搜索效率?一些相關的子查詢的形式也許?我想繼續使用MySQL,但是如果在另一個數據庫服務器中有一個功能可以幫助我做到這一點,我可能會考慮遷移到它。

+0

插入的頻率是多少?什麼是及時性準確度要求? – Drew

+0

我沒有很好的插入率。它可以和數據庫允許的一樣快。我不確定你的意思是及時性的準確性? – Patrick

+0

統計數據是否準確可以有滯後現象?這種類型的信息排除或使可能的不同策略 – Drew

回答

0

要回答你的問題,最好避免使用group bydistinct。首先,我建議爲該表添加一個自動遞增的event_id。這使得可以確定兩行是否相同。

所以,我建議以下查詢:

select e.* 
from events e 
where e.time_stamp between $ts1 and $ts2 and 
     exists (select 1 
       from events e2 
       where e2.pv_name = e.pv_name and 
        e2.time_stamp between $ts1 and $ts2 and 
        e2.event_id < e.event_id 
      ); 

你也想索引:events(time_stamp, pv_name, event_id)events(pv_name, time_stamp, event_id)

這發現事件對。您可以使用select distinct pv_name。但是,這會導致一些額外的處理來刪除重複項。

+0

這似乎沒有比較值? – Patrick

+0

比較什麼值?你的問題是關於獲取名稱列表。 –

+0

在給定時間間隔內具有多個不同值的名稱。 – Patrick

0
SELECT * FROM Customers WHERE pv_name IN 
(SELECT pv_name FROM Customers GROUP BY pv_name HAVING COUNT(*) > 1) AND 
time_stamp BETWEEN 'start_time' and `end_time' 

OR

SELECT * FROM Customers GROUP BY pv_name HAVING MIN(time_stamp) < MAX(time_stamp);

這可能工作。

0

我相信以下可能工作?它可以改進嗎?

-- Chooses a single non null `value` from the `events` table for each `pv_name`. 
CREATE TEMPORARY TABLE single_values (PRIMARY KEY (pv_name)) ENGINE=Memory AS (
SELECT events.pv_name, events.value 
FROM events 
WHERE events.value IS NOT NULL 
GROUP BY events.pv_name); 

-- Finds each `pv_name` that has a `value` different than the one for it in `single_values`. 
-- This is a correlated subquery. 
SELECT single_values.pv_name 
FROM single_values 
WHERE 1 = (
SELECT 1 
FROM events 
WHERE events.pv_name = single_values.pv_name 
AND events.value <> single_values.value 
AND events.value IS NOT NULL 
LIMIT 1); 
相關問題