2013-04-11 81 views
0

混乱,但是,这里的情况:选择项的第一次出现在最后的分组

我们已经有了对应于一个地方坐镇程序以1个分钟的间隔序列号。

Sequence# | Timestamp 
    1  | 2012-04-11 12:00:00 
    2  | 2012-04-11 12:01:00 
    2  | 2012-04-11 12:02:00 
    2  | 2012-04-11 12:03:00 
    3  | 2012-04-11 12:04:00 
    5  | 2012-04-11 12:05:00 
    5  | 2012-04-11 12:06:00 
    6  | 2012-04-11 12:07:00 
    1  | 2012-04-11 12:08:00 
    2  | 2012-04-11 12:09:00 
    2  | 2012-04-11 12:10:00 
    2  | 2012-04-11 12:11:00 
    3  | 2012-04-11 12:12:00 

的序列的持续时间可以改变,但间隔始终是相同的(每1分钟精确)。

正如你所看到的,序列重复。 我如何才能找到Seqence n的最新开始发帖

所以,如果我想搜索序列2,我希望回到2 | 2012-04-11 12:09:00因为它是序列的最新,启动次数2

+0

数据在哪里?在数据库中?或者正在从流中读取? – 2013-04-11 16:26:01

+0

@PhilipKearns:鉴于问题标有[mysql] ... – 2013-04-11 16:27:02

+0

是的,上下文在这里很重要。你想要做什么? – doliver 2013-04-11 16:32:03

回答

4

尝试:

SELECT t1.* FROM `table_name` t1 
LEFT JOIN `table_name` t2 
on t1.`Sequence` = t2.`Sequence` and 
    t1.`Timestamp` = t2.`Timestamp` + interval 1 minute 
WHERE t1.`Sequence`=2 and t2.`Sequence` is null 
ORDER BY t1.`Timestamp` DESC LIMIT 1 

SQLFiddle here

+0

我不认为我遵循这是如何工作的。按照时间顺序,这不会返回序列2的第一次出现吗?你的第二个'ON'需求永远不会是真的,所以左连接总是有t2.Sequence为空,所以Sequence 2的每一个出现都满足这个查询,它会返回最新的。我的查询比这个更复杂,所以尝试这种方法并不容易,所以我需要知道这里真正发生了什么。 – StuckAtWork 2013-04-11 16:45:12

+0

+1,它工作。但如果你能解释它是如何工作的?我的实际数据库(愚蠢)将时间戳存储为“年”,“月”,“日”......字段,而不是选择,所以我需要知道在这里发生了什么逻辑,以便将它复制到这些字段中。 – StuckAtWork 2013-04-11 16:48:45

+0

@StuckAtWork:除了有史以来的第一条记录外,第二个“on”条件将始终为真 - 它将当前时间戳与前一个记录相连,即一分钟前。结合第一个'on'条件将当前记录链接到最后一条记录,**如果它们是相同的序列 - 这使得在外部连接表上使用“is null”条件的左连接实际上是相同的做一个'not exists'(外部连接/ null组合应该在MySQL中执行得更好)。 – 2013-04-11 16:55:20

0

我想这是你想要的...

SELECT * FROM `table_name` WHERE `Sequence`=2 ORDER BY `Timestamp` DESC LIMIT 1 
+0

这个查询会输出'2 | 2012-04-11 12:11:00'而不是'2 | 2012-04-11 12:09:00'如你所说,但我认为'2 | 2012-04-11 12:11:00'实际上是你要找的 – 2013-04-11 16:31:21

+0

我不认为它是 - “最新的**开始**发生”(我强调)。 – 2013-04-11 16:32:29

+0

不是;寻找'12:09:00'。我们给了两个参数,'startSeq'和'endSeq'。我需要从startSeq开始到endSeq结束的那些行的信息,所以如果startSeq是2,我需要序列2的更早的(但仍然是最新的分组)。 – StuckAtWork 2013-04-11 16:33:11

0

这是你想要的吗?

$desired_sequence=2; 

$query="SELECT * FROM `table_name` ORDER BY `Timestamp` DESC"; 
$result = mysql_query($query); 
if (mysql_errno()) { die("ERROR ".mysql_errno($link) . ": " . mysql_error($link)); } 

$found_desired=0; 
while($row = mysql_fetch_array($result)) 
{ 
    if($row['Sequence']==$desired_sequence) 
    { 
     $found_desired=1; 
     $timestamp=$row['Timestamp']; 
    } 

    if(($found_desired==1) && ($row['Sequence']!=$desired_sequence)) 
    { 
     return; // End the while loop because $timestamp will have your desired output. 
    } 
} 
+0

我敢肯定,这种方法是可行的,但它并不像我想的那样优雅或快速。该数据库存储了大约1mil的记录以及几千个唯一的序列号,所以我担心这会在不断询问一些独特的行时对性能产生严重影响。 – StuckAtWork 2013-04-11 16:51:13

+0

让我知道如果你找到更好的方法...我有兴趣知道。 – 2013-04-11 16:54:26

+0

我想如果你可以给初始查询添加一个WHERE,并且只有在给定的时间之后查询结果,那么你肯定是在之后开始的序列。这将大大减少返回的记录。也许甚至有一段时间。您提供的信息越多,效率就越高。 – 2013-04-11 16:56:08

0

我不确定你到底在这里。我写了一些代码,如果数据在文本文件中,这些代码就可以工作。如果数据在数据库中,则会更容易。不过,我从你的例子中假设你有| |分离它不在数据库中的数据。

function findLastOccurenceOfSequence ($sequenceNumber) 
{ 
    if (@!is_int ($sequenceNumber)) 
     throw new Exception ("Expected param1 to be an integer"); 
    $data = file_get_contents ("testFile.txt"); 
    $dataArray = explode ("\n", $data); 
    $dataArray = array_reverse ($dataArray); 
    $returnLine = ""; 
    $sequenceStarted = false; 
    foreach ($dataArray as $key => &$dataLine) 
    { 
     $pieces = explode ("|", $dataLine); 
     if (count ($pieces) != 2) 
      continue; 
     list ($thisSequenceNum, $timeStamp) = $pieces; 
     $thisSequenceNum = intval (trim ($thisSequenceNum)); 
     if ($thisSequenceNum == $sequenceNumber) 
     { 
      $sequenceStarted = true; 
      $returnLine = $dataLine; 
     } 
     else if ($sequenceStarted) 
     { 
      break; 
     } 
    } 

    if ($key == count ($dataArray)) 
    { 
     throw new Exception ("Sequence not found!"); 
    } 

    return $returnLine; 
} 

echo "OCCURRENCE: " . findLastOccurenceOfSequence (2); 
相关问题