我有一份可能有或没有出生日期和/或死亡日期的人员名单。我希望能够按出生日期对它们进行有意义的分类 - 主观术语。
但是 - 如果他们没有出生日期但是他们有一个死亡日期,我想把它们整理到接近其他死亡人员的名单中。
我认识到这不是一个离散的操作 - 当他们的出生日期缺失时,有人应该去哪里。但我大部分时间都在寻找一种很好的近似值。
以下是我想要的示例列表:
Alice 1800 1830
Bob 1805 1845
Carol 1847
Don 1820 1846
Esther 1825 1860
在这个例子中,我很高兴Carol出现在Don之前或之后 - 这是我准备接受的歧义。重要的结果是Carol在相对于她的死亡日期的列表中被排序为死亡日期,而不是按出生日期对死亡日期进行排序。
如果我合并或以其他方式将出生和死亡日期映射在一起,那么什么是行不通的。例如,ORDER BY birth_date, death_date
会把卡罗尔放在以斯帖之后,这是我想的不合适的。
答案 0 :(得分:1)
我认为你必须计算人们最终生活的平均年龄(对于那些同时有出生和死亡日期的人)。并且要么从死亡日期中减去它们,要么将它们添加到出生日期,以便那些没有另一个的人。
在一个查询中执行此操作可能效率不高,并且可能很难看,因为mysql没有窗口函数。您可能更好地预先计算平均生活年龄。但是,让我们尝试在一个查询中执行此操作:
SELECT name, birth_date, death_date
FROM people
ORDER BY COALESCE(
birth_date,
DATE_SUB(death_date, INTERVAL (
SELECT AVG(DATEDIFF(death_date, birth_date))
FROM people
WHERE birth_date IS NOT NULL AND death_date IS NOT NULL
) DAY)
)
答案 1 :(得分:1)
N.B。:我尝试过使用更大的数据集,但它并没有像我期望的那样完全正常工作。
尝试使用此查询(它需要id
主键列):
SELECT * FROM people p
ORDER BY (
CASE WHEN birth IS NOT NULL THEN (
SELECT ord FROM (
SELECT id, @rnum := @rnum + 1 AS ord
FROM people, (SELECT @rnum := 0) r1
ORDER BY (CASE WHEN birth IS NOT NULL THEN 0 ELSE 1 END), birth, death
) o1
WHERE id = p.id
) ELSE (
SELECT ord FROM (
SELECT id, @rnum := @rnum + 1 AS ord
FROM people, (SELECT @rnum := 0) r2
ORDER BY (CASE WHEN death IS NOT NULL THEN 0 ELSE 1 END), death, birth
) o2
WHERE id = p.id
)
END)
;
我所做的基本上是对数据集进行两次排序,一次按出生日期,然后按死亡日期排序。然后我使用这两个排序列表将最终顺序分配给原始数据集,首先从出生排序列表中选择位置,并在行没有出生日期时使用死亡排序列表中的位置。 / p>
以下是该查询的一些问题:
这是我用来编写它的表,用MySQL 5.6.21测试过(我无法理解为什么,但SQL Fiddle拒绝使用Create script error
我的脚本,所以我可以没有为你提供一个实例。
创建表:
CREATE TABLE `people` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(50) NOT NULL,
`birth` INT(11) NULL DEFAULT NULL,
`death` INT(11) NULL DEFAULT NULL,
PRIMARY KEY (`id`)
);
数据(我实际上稍微改变了你的数据):
INSERT INTO `people` (`name`, `birth`, `death`) VALUES ('Alice', 1800, NULL);
INSERT INTO `people` (`name`, `birth`, `death`) VALUES ('Bob', 1805, 1845);
INSERT INTO `people` (`name`, `birth`, `death`) VALUES ('Carol', NULL, 1847);
INSERT INTO `people` (`name`, `birth`, `death`) VALUES ('Don', 1820, 1846);
INSERT INTO `people` (`name`, `birth`, `death`) VALUES ('Esther', 1815, 1860);
答案 2 :(得分:0)
您可以使用子查询选择合适的生日来进行分类 然后是一个工会加入与生日的记录 例如:
select d1.name, null as birthdate, d1.deathdate, max(d2.birthdate) sort from
d as d1, d as d2
where d1.birthdate is null and d2.deathdate <=d1.deathdate
group by d1.name, d1.deathdate
union all
select name, birthdate, deathdate, birthdate from d
where birthdate is not null
order by 4
答案 3 :(得分:-1)
不确定这是否有效,但值得一试(我无法在MySQL上测试),所以试着猜测:
order by case birth_date when null then death_date else birth_date end case