我想在与患者相关的数据库中执行以下操作:
其中一些取决于您的特定数据库实现。然而,一般的部分是年龄类别的概念。这是一个实现,使用 ID 作为代理键并编写为与 SQL Server 一起使用(这意味着您可能需要稍微更改语法以使其与其他产品一起使用):
CREATE TABLE dbo.AgeCategory
(
ID tinyint identity(1,1) NOT NULL,
MinimumAge tinyint NOT NULL,
Name varchar(20) NOT NULL
);
ALTER TABLE dbo.AgeCategory ADD CONSTRAINT [PK_AgeCategory] PRIMARY KEY(ID);
CREATE UNIQUE INDEX [IX_MinimumAge] ON dbo.AgeCategory(MinimumAge) INCLUDE(Name);
INSERT INTO dbo.AgeCategory(MinimumAge, Name) values
(0, 'Newborn'),
(1, 'Infant'),
(2, 'Toddler'),
(5, 'Child'),
(12, 'Adolescent'),
(18, 'Adult'),
(30, 'Some marker'),
(40, 'Something else'),
(50, '50+'),
(65, 'Retiree'),
(90, 'Amazing');
Run Code Online (Sandbox Code Playgroud)
我已经用样本年龄和类别填充了它。下面是如何使用此表的示例。我将使用出生日期填充 Person 表,然后查询以查找他们的年龄类别。
这是示例数据:
CREATE TABLE dbo.Person
(
ID int identity(1,1) NOT NULL,
Name varchar(50) NOT NULL,
DateOfBirth datetime NOT NULL
);
insert into dbo.Person(Name, DateOfBirth) values
('Bob', '1983-01-08'),
('Mary', '1976-05-05'),
('Jane', '1960-04-01'),
('Tony', '2012-08-16'),
('Marcy', '1955-06-11'),
('Carl', '1930-12-24'),
('Joseph', '1918-11-11');
Run Code Online (Sandbox Code Playgroud)
这是查询:
with people as
(
select
Name,
DateOfBirth,
datediff(day, dateofbirth, current_timestamp) / 365.25 as YearsOld
from
dbo.Person p
)
select
p.Name,
p.DateOfBirth,
p.YearsOld,
a.MinimumAge,
a.Name as AgeCategory
from
people p
cross apply
(
select top 1
ac.MinimumAge,
ac.Name
from
dbo.AgeCategory ac
where
ac.MinimumAge < p.YearsOld
order by
ac.MinimumAge desc
) a;
Run Code Online (Sandbox Code Playgroud)
请注意,此查询适用于 SQL Server,但我不能保证任何其他产品的语法都相同(或者这是解决 SQL Server 以外的任何产品的此问题的相对有效的方法)。我们正在做的是根据出生日期计算年龄。然后,我们可以使用 CROSS APPLY 函数将其应用于年龄类别表。这将返回特定行的一个最佳年龄类别。
请注意,您可以将 AgeCategory 表修改为具有两个年龄值:MinimumAge 和 MaximumAge。这将摆脱 cross apply 语句并用 INNER JOIN 替换它,但缺点是你可能会得到重叠的行:如果你的最小年龄为 10 岁,最大年龄为 20 岁,然后另一行与最小年龄为 15 岁,最大年龄为 25 岁,对于 15 岁到 20 岁之间的每个人,您将有两个结果。单项表摆脱了这个问题,而无需引入触发器或数据检查,除了年龄列上的唯一索引,但在数据集足够大的情况下,性能可能会更高。
对于SQL SERVER,添加此列的一种非常简单的方法是作为计算列,由于 CURRENT_TIMESTAMP 依赖性,这将是不确定的。
alter table PATIENT add AgeCategory as
CASE
WHEN DateAdd(Year,1,DOB) > Current_Timestamp then 'infant'
WHEN DateAdd(Year,4,DOB) > Current_Timestamp then 'toddler'
WHEN DateAdd(Year,10,DOB) > Current_Timestamp then 'children'
WHEN DateAdd(Year,14,DOB) > Current_Timestamp then 'tween'
WHEN DateAdd(Year,18,DOB) > Current_Timestamp then 'teenager'
WHEN DateAdd(Year,65,DOB) > Current_Timestamp then 'adult'
ELSE 'elderly'
END;
Run Code Online (Sandbox Code Playgroud)
即对于这个表:
CREATE TABLE PATIENT
(
ID integer primary key,
FullName varchar(255) NOT NULL,
DOB datetime NOT NULL
);
insert into PATIENT(ID, FullName, DOB) values
(1, 'John Doe', '1900-01-01'),
(2, 'Jane Doe', '1960-02-03'),
(3, 'Joe Public', '1990-05-06'),
(4, 'Bob the Builder', '2007-08-09'),
(5, 'Ecco the Dolphin', '2009-12-31'),
(6, 'Foo', '2012-01-09'),
(7, 'Bar', '2012-11-11');
Run Code Online (Sandbox Code Playgroud)
以下查询:
SELECT * FROM PATIENT
Run Code Online (Sandbox Code Playgroud)
返回:
ID FullName DOB AgeCategory
----------- -------------------- ----------------------- -----------
1 John Doe 1900-01-01 00:00:00.000 elderly
2 Jane Doe 1960-02-03 00:00:00.000 adult
3 Joe Public 1990-05-06 00:00:00.000 adult
4 Bob the Builder 2007-08-09 00:00:00.000 children
5 Ecco the Dolphin 2009-12-31 00:00:00.000 toddler
6 Foo 2012-01-09 00:00:00.000 infant
7 Bar 2012-11-11 00:00:00.000 infant
Run Code Online (Sandbox Code Playgroud)
AgeCategory
无法持久化 - 从本质上讲,它可以根据时间在一个选择和下一个选择之间更改。每个 DBMS 的日期操作函数都不同,但模式是相似的。
例如,这是 SQLite ( SQLFiddle )的版本
create view PatientWithAgeCategory as
select ID, FullName, DOB,
CASE
WHEN Date(DOB, "+1 year") > Current_Timestamp then 'infant'
WHEN Date(DOB, "+18 year") > Current_Timestamp then 'children'
WHEN Date(DOB, "+65 year") > Current_Timestamp then 'adult'
ELSE 'elderly'
END AgeCategory
from Patient;
Run Code Online (Sandbox Code Playgroud)