考虑下表:
someId INTEGER #PK
ageStart TINYINT(3)
ageEnd TINYINT(3)
dateBegin INTEGER
dateEnd INTEGER
dateBegin
和dateEnd
的日期表示为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行样本数据
答案 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
我怀疑只用一个查询即可完成......