我在数据库中有多个相关表,每个表都可以单独更新并拥有自己的LastUpdated Date字段。在其中一个表中,有多个LastUpdated字段,每个字段指示该记录的更新源。我们通常将这些多个表作为带有连接的单个项进行查询,因此我想知道每条记录中所有连接中最近的LastUpdated记录是什么。我知道这可以通过许多子查询来实现,但我想知道是否存在Coalesce函数的某些内容,您可以将许多字段传递给它并返回第一个非null值。
所以它会读起来像:
SELECT a.a_id,
a.name,
b.b_id,
b.detail,
c.c_id,
c.otherfield,
Maxdate(a.lastupdated, a.lastupdatedfromweb, b.lastupdated,
c.lastupdated) AS
LastUpdatedDate
FROM a
INNER JOIN b
ON a.a_id = b.a_id
INNER JOIN c
ON b.b_id = c.b_id
有什么想法吗?这可以写成自定义函数还是存在于框中?我正在研究SQL Server 2005和2008,如果这有帮助的话。
答案 0 :(得分:2)
在2008年以上,您可以使用CROSS APPLY
为每个日期创建一行,然后选择最大值:
SELECT
a.a_Id,
a.Name,
b.b_Id,
b.Detail,
c.c_Id,
c.OtherField,
ld.LastUpdatedDate
FROM
a INNER JOIN b ON a.a_Id = b.a_Id
INNER JOIN c ON b.b_Id = c.b_Id
CROSS APPLY
( SELECT LastUpdatedDate = MAX(LastUpdatedDate)
FROM (VALUES
(a.LastUpdated),
(a.LastUpdatedFromWeb),
(b.LastUpdated),
(c.LastUpdated)
) d (LastUpdatedDate)
) ld
您也可以将此作为相关子查询执行,但在优化期间,SQL Server会将相关子查询重写为OUTER APPLY
,因此我更愿意自己切出一步并自行编写APPLY,因为我发现了一些不寻常的行为当SQL解构相关子查询并将其重写为APPLY时。更多细节是described in this answer
2005年,我认为您需要使用稍微不同的方法,因为它不支持表值构造函数:
SELECT
a.a_Id,
a.Name,
b.b_Id,
b.Detail,
c.c_Id,
c.OtherField,
ld.LastUpdatedDate,
( SELECT MAX(CASE Number
WHEN 1 THEN a.LastUpdated
WHEN 2 THEN a.LastUpdatedFromWeb
WHEN 3 THEN b.LastUpdated
WHEN 4 THEN c.LastUpdated
END)
FROM (SELECT TOP 4 Number = ROW_NUMBER() OVER(ORDER BY object_id)
FROM sys.all_objects) n
) AS LastUpdated
FROM
a INNER JOIN b ON a.a_Id = b.a_Id
INNER JOIN c ON b.b_Id = c.b_Id;
或者:
SELECT
a.a_Id,
a.Name,
b.b_Id,
b.Detail,
c.c_Id,
c.OtherField,
ld.LastUpdatedDate,
( SELECT MAX(LastUpdated)
FROM ( SELECT a.LastUpdated UNION ALL
SELECT a.LastUpdatedFromWeb UNION ALL
SELECT b.LastUpdated UNION ALL
SELECT c.LastUpdated
) d
) AS LastUpdated
FROM
a INNER JOIN b ON a.a_Id = b.a_Id
INNER JOIN c ON b.b_Id = c.b_Id;
不幸的是我不再安装任何2005实例,所以我无法测试它。
修改强>
刚才意识到你也想要这个领域的来源,并且还记得2005年确实支持使用APPLY,所以对于2008 +:
SELECT
a.a_Id,
a.Name,
b.b_Id,
b.Detail,
c.c_Id,
c.OtherField,
ld.LastUpdatedDate,
ld.FieldName
FROM
a INNER JOIN b ON a.a_Id = b.a_Id
INNER JOIN c ON b.b_Id = c.b_Id
CROSS APPLY
( SELECT TOP 1 LastUpdatedDate, FieldName
FROM (VALUES
(a.LastUpdated, 'a.LastUpdated'),
(a.LastUpdatedFromWeb, 'a.LastUpdatedFromWeb'),
(b.LastUpdated, 'b.LastUpdated'),
(c.LastUpdated, 'c.LastUpdated')
) d (LastUpdatedDate, FieldName)
ORDER BY LastUpdated DESC
) ld
2005年:
SELECT
a.a_Id,
a.Name,
b.b_Id,
b.Detail,
c.c_Id,
c.OtherField,
ld.LastUpdatedDate,
ld.FieldName
FROM
a INNER JOIN b ON a.a_Id = b.a_Id
INNER JOIN c ON b.b_Id = c.b_Id
CROSS APPLY
( SELECT TOP 1 LastUpdatedDate = LastUpdated, FieldName
FROM (
SELECT a.LastUpdated, FieldName = 'a.LastUpdated' UNION ALL
SELECT a.LastUpdatedFromWeb, 'a.LastUpdatedFromWeb' UNION ALL
SELECT b.LastUpdated, 'b.LastUpdated' UNION ALL
SELECT c.LastUpdated, 'c.LastUpdated'
) d
ORDER BY LastUpdated DESC
) ld
答案 1 :(得分:0)
SELECT
a.a_Id,
a.Name,
b.b_Id,
b.Detail,
c.c_Id,
c.OtherField,
MAX(SELECT a.LastUpdated, a.LastUpdatedFromWeb, b.LastUpdated, c.LastUpdated FROM a INNER JOIN b ON a.a_Id = b.a_Id INNER JOIN c ON b.b_Id = c.b_Id) AS LastUpdatedDate
FROM
a INNER JOIN b ON a.a_Id = b.a_Id
INNER JOIN c ON b.b_Id = c.b_Id