2011-05-04 84 views
0

我有一個表,看起來像這樣:如何解決這個MySQL查詢?

CREATE TEMPORARY TABLE MainList (
    `pTime` int(10) unsigned NOT NULL, 
    `STD` double NOT NULL, 
    PRIMARY KEY (`pTime`) 
) ENGINE=MEMORY; 


+------------+-------------+ 
| pTime  | STD   | 
+------------+-------------+ 
| 1106080500 | -0.5058072 | 
| 1106081100 | -0.82790455 | 
| 1106081400 | -0.59226294 | 
| 1106081700 | -0.99998194 | 
| 1106540100 | -0.86649279 | 
| 1107194700 | 1.51340543 | 
| 1107305700 | 0.96225296 | 
| 1107306300 | 0.53937716 | 
+------------+-------------+ .. etc 

的ptime是我的主鍵。

我想做一個查詢,對於我表中的每一行,都會找到第一個pTime,其中STD有一個翻轉符號,與上表的STD相比距離0更遠。 (爲簡單起見,試想一下,我找了0-STD)

這裏是輸出我想要的例子:

+------------+-------------+------------+-------------+ 
| pTime  | STD   | pTime_Oppo | STD_Oppo | 
+------------+-------------+------------+-------------+ 
| 1106080500 | -0.5058072 | 1106090400 | 0.57510881 | 
| 1106081100 | -0.82790455 | 1106091300 | 0.85599817 | 
| 1106081400 | -0.59226294 | 1106091300 | 0.85599817 | 
| 1106081700 | -0.99998194 | 1106091600 | 1.0660959 | 
+------------+-------------+------------+-------------+ 

我似乎無法得到它的權利! 我試過以下內容:

SELECT DISTINCT 
    MainList.pTime, 
    MainList.STD, 
    b34d1.pTime, 
    b34d1.STD 
FROM 
    MainList 
JOIN b34d1 ON(
    b34d1.pTime > MainList.pTime 
    AND(
     (
      MainList.STD > 0 
      AND b34d1.STD <= 0 - MainList.STD 
     ) 
     OR(
      MainList.STD < 0 
      AND b34d1.STD >= 0 - MainList.STD 
     ) 
    ) 
); 

該代碼只是凍結了我的服務器。

PS表b34d1就像MainList,除了它包含更多的元素:在集

mysql> select STD, Slope from b31d1 limit 10; 
+-------------+--------------+ 
| STD   | Slope  | 
+-------------+--------------+ 
| -0.44922675 | -5.2016129 | 
| -0.11892021 | -8.15249267 | 
| 0.62574686 | -10.19794721 | 
| 1.10469057 | -12.43768328 | 
| 1.52917352 | -13.08651026 | 
| 1.61803899 | -13.2441349 | 
| 1.82686555 | -12.04912023 | 
| 2.07480736 | -11.22067449 | 
| 2.45529961 | -7.84090909 | 
| 1.86468335 | -6.26466276 | 
+-------------+--------------+ 
mysql> select count(*) from b31d1; 
+----------+ 
| count(*) | 
+----------+ 
| 439340 | 
+----------+ 

1行(0.00秒)

事實上MainList只是一個過濾b34d1的版本,它使用的MEMORY引擎

mysql> show create table b34d1; 
+-------+----------------------------------------------------------------------------------------------- 
-------------------------------------------------------------------------------------------------------+ 
| Table | Create Table 
                             | 
+-------+----------------------------------------------------------------------------------------------- 
-------------------------------------------------------------------------------------------------------+ 
| b34d1 | CREATE TABLE `b34d1` (
    `pTime` int(10) unsigned NOT NULL, 
    `Slope` double NOT NULL, 
    `STD` double NOT NULL, 
    PRIMARY KEY (`pTime`) 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 MIN_ROWS=339331 MAX_ROWS=539331 PACK_KEYS=1 ROW_FORMAT=FIXED | 
+-------+----------------------------------------------------------------------------------------------- 
-------------------------------------------------------------------------------------------------------+ 

編輯:我只是做了一個小實驗,我感到非常困惑的結果:

SELECT DISTINCT 
    b34d1.pTime, 
    b34d1.STD, 
    Anti.pTime, 
    Anti.STD 

FROM 
    b34d1 

LEFT JOIN b34d1 As Anti ON(
    Anti.pTime > b34d1.pTime 
    AND(
     (
      b34d1.STD > 0 
      AND b34d1.STD <= 0 - Anti.STD 
     ) 
     OR(
      b34d1.STD < 0 
      AND b34d1.STD >= 0 - Anti.STD 
     ) 
    ) 
) limit 10; 

+------------+-------------+------------+------------+ 
| pTime  | STD   | pTime  | STD  | 
+------------+-------------+------------+------------+ 
| 1104537600 | -0.70381962 | 1104539100 | 0.73473692 | 
| 1104537600 | -0.70381962 | 1104714000 | 1.46733274 | 
| 1104537600 | -0.70381962 | 1104714300 | 2.02097356 | 
| 1104537600 | -0.70381962 | 1104714600 | 2.60642099 | 
| 1104537600 | -0.70381962 | 1104714900 | 2.01006557 | 
| 1104537600 | -0.70381962 | 1104715200 | 1.97724189 | 
| 1104537600 | -0.70381962 | 1104715500 | 1.85683704 | 
| 1104537600 | -0.70381962 | 1104715800 | 1.2754127 | 
| 1104537600 | -0.70381962 | 1104716100 | 0.87900156 | 
| 1104537600 | -0.70381962 | 1104716400 | 0.72957739 | 
+------------+-------------+------------+------------+ 

爲什麼第一個pTime下的所有值都是一樣的?

+0

我幫你解決了你的問題。它應該儘快解決。編輯:或者我可以被特魯法擊敗! – Nic 2011-05-04 04:07:24

+0

@Mike,請不要這是不是一個論壇,所以你格式化你的問題不同,請點擊問題或答案文本區域中的橙色問號來了解如何。謝謝! – Trufa 2011-05-04 04:10:46

+0

@melee:hehe對不起:) – Trufa 2011-05-04 04:11:07

回答

0

任何解決方案標誌註定對大型數據集無效,因爲它使索引變得不可能。

您正在SP中創建一個臨時表,因此您可以在不丟失任何東西的情況下更改它的模式,添加一個存儲STD標誌並存儲STD本身的列無符號會給您巨大的性能提升,因爲您可以簡單地找到更大的PTIME並用不同的符號更大的性病的全部條件。在這樣的查詢中使用索引(STD_positive保持性病徵):

SELECT * from mainlist m 
LEFT JOIN mainlist mu 
ON mu.pTime = (SELECT md.pTime FROM mainlist md 
      WHERE m.pTime < md.pTime 
      AND m.STD < md.STD 
      AND m.STD_positive <> md.STD_positive 
      ORDER BY md.pTime 
      LIMIT 1) 

LEFT JOIN這裏需要返回不要有更大的STD行。如果你不需要他們使用簡單的JOIN。即使在大量記錄中,這個查詢也應該運行正常,並且基於仔細檢查EXPLAIN輸出的適當索引,從STD索引開始。

1

從一行中選擇具有某些聚集統計信息(如最小值或最大值)的其他字段在SQL中有點麻煩。這樣的查詢並不那麼簡單。您通常需要額外的連接或子查詢。例如:

SELECT m.pTime, m.STD, m2.pTime AS pTime_Oppo, m2.STD AS STD_Oppo 
    FROM MainList AS m 
    JOIN 
     (SELECT m1.pTime, MIN(m2.pTime) AS pTime_Oppo 
     FROM MainList AS m1 
      JOIN MainList AS m2 
      ON m1.pTime < m2.pTime AND SIGN(m1.STD) != SIGN(m2.STD) 
     WHERE ABS(m1.STD) <= ABS(m2.std) 
     GROUP BY m1.pTime 
    ) AS oppo ON m.pTime = oppo.pTime 
    JOIN MainList AS m2 ON oppo.pTime_Oppo = m2.pTime 
; 

使用樣本數據:

INSERT INTO MainList (`pTime`, `STD`) 
    VALUES 
(1106080500, -0.5058072), 
(1106081100, -0.82790455), 
(1106081400, -0.59226294), 
(1106081700, -0.99998194), 
(1106090400, 0.57510881), 
(1106091300, 0.85599817), 
(1106091600, 1.0660959), 
(1106540100, -0.86649279), 
(1107194700, 1.51340543), 
(1107305700, 0.96225296), 
(1107306300, 0.53937716), 
; 

的結果是:檢查需要基於像ABS或SIGN或任何類似功能

+------------+-------------+------------+-------------+ 
| pTime  | STD   | pTime_Oppo | STD_Oppo | 
+------------+-------------+------------+-------------+ 
| 1106080500 | -0.5058072 | 1106090400 | 0.57510881 | 
| 1106081100 | -0.82790455 | 1106091300 | 0.85599817 | 
| 1106081400 | -0.59226294 | 1106091300 | 0.85599817 | 
| 1106081700 | -0.99998194 | 1106091600 | 1.0660959 | 
| 1106090400 | 0.57510881 | 1106540100 | -0.86649279 | 
| 1106091300 | 0.85599817 | 1106540100 | -0.86649279 | 
| 1106540100 | -0.86649279 | 1107194700 | 1.51340543 | 
+------------+-------------+------------+-------------+
0
SELECT 
    m.pTime, 
    m.STD, 
    mo.pTime AS pTime_Oppo, 
    -mo.STD AS STD_Oppo 
FROM MainList m 
    INNER JOIN (
    SELECT 
     pTime, 
     -STD AS STD 
    FROM MainList 
) mo ON m.STD > 0 AND mo.STD > m.STD 
     OR m.STD < 0 AND mo.STD < m.STD 
    LEFT JOIN (
    SELECT 
     pTime, 
     -STD AS STD 
    FROM MainList 
) mo2 ON mo.STD > 0 AND mo2.STD > m.STD AND mo.STD > mo2.STD 
     OR mo.STD < 0 AND mo2.STD < m.STD AND mo.STD < mo2.STD 
WHERE mo2.pTime IS NULL