找到没有存储过程的相邻行

时间:2010-03-10 14:13:53

标签: mysql

考虑下表:

someId INTEGER #PK
ageStart TINYINT(3)
ageEnd TINYINT(3)
dateBegin INTEGER
dateEnd INTEGER

dateBegindateEnd的日期表示为1800-12-28后的天数......

考虑一些样本数据:

someId | ageStart | ageEnd | dateStart | dateEnd
------------------------------------------------
   203 |       16 |     25 |     76533 |   76539   \
   506 |       16 |     25 |     76540 |   76546    adjacent rows
   384 |       16 |     25 |     76547 |   76553   /
   342 |       16 |     25 |     76563 |   76569   \
   545 |       16 |     25 |     76570 |   76576    adjacent rows
   764 |       16 |     25 |     76577 |   76583   /

(当然会混合任意行,我只想说明2个相关的行集)

是否可以在没有存储过程的情况下找到给定年龄类别(ageStart到ageEnd)的相邻行?邻接的标准是:dateStart是在前一个找到的行dateEnd之后的第1天。

例如,给定上面的示例数据,如果我使用以下参数查询它:

ageStart = 16
ageEnd = 25
dateStart = 76533

我希望它返回示例数据的第1,2和3行,因为它们的日期是相邻的(dayStart是前一行的dateEnd的第二天)。

ageStart = 16
ageEnd = 25
dateStart = 76563

...会给我第4,5和6行样本数据

3 个答案:

答案 0 :(得分:1)

您可以认为您的数据处于父子关系中:如果子项的startDate等于父项的endDate + 1,则记录是(父)记录的子项。对于分层数据(具有父子关系), 嵌套集模型允许您在没有存储过程的情况下查询数据。您可以在此处找到嵌套集模型的简要说明:

http://mikehillyer.com/articles/managing-hierarchical-data-in-mysql/

我们的想法是以巧妙的方式为您的记录编号,以便您可以使用简单查询而不是递归存储过程。

虽然查询以这种方式存储的分层数据非常容易,但在添加新记录时需要注意。在嵌套集模型中添加新记录需要更新现有记录。在您的使用案例中,这可能是可接受的,也可能是不可接受的。

答案 1 :(得分:1)

如果您的表中有大量数据,但尝试此操作可能效率不高:

SELECT b.*
FROM
(SELECT @continue:=2) init,
(
 SELECT * 
 FROM ageTable 
 WHERE ageStart=16 AND 
       ageEnd=25   AND 
       dateStart=76533
) a 
  INNER JOIN (
   SELECT *
   FROM ageTable
   ORDER BY dateStart
  ) b ON (
    b.ageStart=a.ageStart AND
    b.ageEnd=a.ageEnd     AND
    b.dateStart>=a.dateStart
  ) 
  LEFT JOIN ageTable c ON (
    c.dateStart=b.dateEnd+1 AND
    c.ageStart=b.ageStart   AND 
    c.ageEnd=b.ageEnd
  )
WHERE 
 CASE
  WHEN @continue=2 THEN
   CASE
    WHEN c.someId IS NULL THEN
     @continue:=1
    ELSE
     @continue
   END
  WHEN @continue=1 THEN
   @continue:=0
  ELSE
   @continue
 END

答案 2 :(得分:0)

好吧,你可以生成一个以特定方式排序的结果集并使用LIMIT来获取它的第一条记录。

例如,通过列表中的dateEnd获取下一条记录:

SELECT *
FROM `table`
WHERE `dateEnd` > '76546'
ORDER BY `dateEnd`
LIMIT 1

你会得到:

384 |       16 |     25 |     76547 |   76553

前一行:

SELECT *
FROM `table`
WHERE `dateEnd` < '76546'
ORDER BY `dateEnd` DESC
LIMIT 1

你会得到:

   203 |       16 |     25 |     76533 |   76539

我怀疑只用一个查询即可完成......