请原谅我的问题的简单性,我有一个脑屁:
这是我的表架构:
Foo( FooId, BarDate dateTime, Baz int )
鉴于此查询
SELECT
MAX( Foo.BarData )
FROM
Foo
WHERE
Foo.Baz = 2
AND
Foo.BarData < @dateParameter
在某些情况下,此查询返回NULL
,因为没有符合条件的行,在这些情况下,我希望查询返回相同的值,Foo.Baz = 0
除外。
我可以使用两个子查询来完成它,但它似乎是一个黑客。是不是有更好的方法?
SELECT
COALESCE( Attempt1.BarData, Attempt2.BarData )
FROM
(
SELECT
MAX( Foo.BarData ) As BarData
FROM
Foo
WHERE
Foo.Baz = 2
AND
Foo.BarData < @dateParameter
) As Attempt1
OUTER JOIN
(
SELECT
MAX( Foo.BarData ) As BarData
FROM
Foo
WHERE
Foo.Baz = 0
AND
Foo.BarData < @dateParameter
) As Attempt2 ON 1 = 1
答案 0 :(得分:6)
只需选择两行并将结果限制为1行,订购首选行为
SELECT TOP 1
MAX( Foo.BarData )
FROM
Foo
WHERE
((Foo.Baz = 2) OR
(Foo.Baz = 0))
AND
Foo.BarData < @dateParameter
GROUP BY Foo.Baz
ORDER BY Foo.Baz DESC
答案 1 :(得分:4)
可以在同一查询中获取两个Foo.Baz的MAX
值,使用CASE
分隔原始数据
SELECT COALESCE(MAX(CASE WHEN Foo.Baz = 2 THEN Foo.BarDate ELSE NULL END)
, MAX(CASE WHEN Foo.Baz = 0 THEN Foo.BarDate ELSE NULL END)
)
FROM Foo
WHERE Foo.Baz IN (0,2)
AND Foo.BarDate < @dateParameter
答案 2 :(得分:1)
SELECT COALESCE(
(SELECT MAX(Foo.BarData) FROM Foo WHERE Foo.Baz = 2 AND Foo.BarData < @dateParameter),
(SELECT MAX(Foo.BarData) FROM Foo WHERE Foo.Baz = 0 AND Foo.BarData < @dateParameter)
)
根据您的平台,这可能比其他答案有更好的计划。在SQL Server上,您不需要FROM子句。在Oracle上,您可以从DUAL中进行选择。其他系统可能需要一个返回单行的虚拟表达式。
OP的查询可能刚刚用交叉连接而不是外连接编写。这可能是它感觉像黑客的部分原因。我说你的要求并不是一个普通的sql-esque问题,所以任何答案都会这样。
如果你想强调典型的路径是Foo.Baz = 2,你可能会喜欢它的样子:
SELECT COALESCE(
MAX(Foo.BarData),
(SELECT MAX(Foo.BarData) FROM Foo WHERE Foo.Baz = 0 AND Foo.BarData < @dateParameter)
)
FROM Foo
WHERE Foo.Baz = 2 AND Foo.BarData < @dateParameter)
答案 3 :(得分:0)
只是为了完成列表,您也可以使用IF..ELSE,如下所示。
IF EXISTS (SELECT 1 FROM Foo WHERE Foo.Baz = 2)
BEGIN
SELECT MAX( Foo.BarData)
FROM Foo
WHERE Foo.Baz = 2
AND Foo.BarData < @dateParameter
END
ELSE
BEGIN
SELECT MAX( Foo.BarData)
FROM Foo
WHERE Foo.Baz = 0
AND Foo.BarData < @dateParameter
END
如果它对你有所帮助。