0

有没有办法在不使用 CASE WHEN 的情况下重写使用 CASE WHEN 结构的 Transact SQL 语句来做同样的事情?

我正在使用具有内置查询设计器和自己的伪 SQL 的产品。它对我可以与 SQL Server 和 Oracle 一起使用的内容有限制。所以我有这个专栏,当底层数据库是 Oracle 时,使用 DECODE(支持)。但是,我需要让它与 SQL Server 一起使用,并且不支持 CASE WHEN。

我试图转换的语句类似于

Decode (StatusColumn,  'Value 1',
Decode(Sign(Now()-TargetDateColumn)),1,'Past
Due', 'Outstanding'),  'Value 2',
Decode(Sign(Now()-TargetDateColumn)),1,'Past
Due', 'Outstanding'),  'Value 3',
Decode(Sign(Now()-TargetDateColumn)),1,'Past
Due', 'Outstanding'),  'Value 4')

我有一组有限的 T-SQL 选项可供使用,CASE WHEN 不是一个选项。我确实有 IsNull 和 Coalesce,但我不确定他们是否会帮助我解决这个问题。

不要为日期计算而烦恼,这些都解决了。

我在这里搜索了 CASE WHEN 问题,但无济于事。

谢谢!

更新:

我意识到我应该提供更多关于限制原因的详细信息,因为这是开发人员的资源,并且会假定这是一个开发产品。它不是。

我正在使用具有内置查询设计器和自己的伪 SQL 的企业软件产品。它对我可以与 SQL Server 和 Oracle 一起使用的内容有限制。基本上,所有不破坏内置查询引擎解析的东西都是游戏。这意味着所有批准的函数和表达式,加上所有数据抽象(对应于数据库中的物理表的内部对象和使用产品创建的其他查询),加上 Oracle SQL 或 Transact SQL 中没有显式破坏解析的所有内容.

CASE WHEN 对我不起作用的原因是它破坏了查询引擎对伪 SQL 的解析。

最终,我想尝试:

  1. 仅使用产品的查询设计器通过解析的 SQL 或
  2. 使用来自 SQL Server 数据库和查询设计器的一些额外资源来完成它。

根据我得到的几个好的答案,到目前为止,这是对我有用的方法。

Jason DeFontes 建议我可以使用数据库视图来执行 CASE WHEN 规则,这属于上面的#2。它对我有用,因为视图足够动态,我不必对其进行维护(与richartallent 的真值表方法相反,我认为它接近 Jason 的方法)。Pascal 关于创建函数的建议将遵循相同的思路,但可能会破坏解析。

因此,我创建了一个数据库视图,它使用 CASE WHEN 进行所有转换,并将其添加到查询的 SQL 中,将其与现有 SQL 结合起来,它工作得很好。我意识到我可能会增加数据库引擎的开销,因为它必须检索相同的数据集两次(一次用于视图,一次用于查询),但这是几乎不成问题的情况之一。

鉴于这种“使用视图来混淆它”的设计对我有用,我想知道更有效的方法是什么:

  • 使用带有 CASE WHEN 的选择;
  • 使用 CTE(再次,richardtallent);
  • 使用联合所有(HLGEM);
  • 使用子查询(MisterZimbu);

我仍然会检查 Aramis wyler 的建议,因为它可能属于上面的#1。

目前,杰森的回答被接受了。考虑到我在视图中使用了 CASE WHEN,也许问题的标题最终选择不当。我提高了每个人的建议,在这个过程中有所帮助。我不知道这是否会影响您的声誉,但我认为这是一件好事。

再次,我要感谢大家的帮助,并恳请您对您认为不合适的问题进行编辑(这是我的第一个问题,英语是我的第二语言)。

4

6 回答 6

4

你有工会吗?也许您可以在 where 子句中为每个条件编写一个查询条件,并将它们联合在一起。

于 2009-11-05T18:20:25.740 回答
3

你能写自定义子查询吗?如果您甚至无法访问 CASE WHEN,则可能不会,但这也可能有效:

select
    ...,
    coalesce(c1.value, c2.value, c3.value, ..., <default value>)
from MyTable
left join (select <result 1> as value) c1 on <first condition>
left join (select <result 2> as value) c2 on <second condition>
left join (select <result 3> as value) c3 on <third condition>
于 2009-11-05T19:04:27.330 回答
3

您可以将 CASE/WHEN 逻辑移动到视图中,然后让工具查询视图吗?

于 2009-11-05T20:04:40.100 回答
1

编写一个使用 CASE WHEN 执行计算的函数。

于 2009-11-05T18:10:05.147 回答
1

它很丑陋,并且取决于您拥有的值的数量,它可能不可行。但严格来说,我认为这样的内容可以作为上述查询段的翻译:

从表名中选择 'PastDue' where Now() > TargetDateColumn and (StatusColumn = 'Value 1' or StatusColumn = 'Value 2' or StatusColumn = 'Value 3') union select 'Outstanding' where Now() < TargetDateColumn and (StatusColumn = 'Value 1' or StatusColumn = 'Value 2' or StatusColumn = 'Value 3') union select 'Value 4' where NOT (StatusColumn = 'Value 1' or StatusColumn = 'Value 2' or StatusColumn = 'Value 3')

于 2009-11-05T19:07:13.953 回答
1

我不确定我是否理解您的代码,但这应该会给您一个不同方法的想法。

首先,创建一个表:

CREATE TABLE StatusLookup(
   value nvarchar(255),
   datesign shortint,
   result varchar(255));

现在,用真值表填充它(这里显然有很多重复的逻辑,也许这应该是两个真值表,它们之间有一个 CROSS JOIN):

INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 1', -1, 'Outstanding')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 1', 0, 'Outstanding')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 1', 1, 'Past Due')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 2', -1, 'Outstanding')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 2', 0, 'Outstanding')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 2', 1, 'Past Due')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 3', -1, 'Outstanding')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 3', 0, 'Outstanding')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 3', 1, 'Past Due')

最后,加入并提供默认答案:

SELECT mytable.*, COALESCE(statuslookup.result, 'Value 4')
FROM
    mytable LEFT JOIN statuslookup ON
        statuslookup.value = StatusColumn
        AND statuslookup.datesign = Sign(Now()-TargetDateColumn)

这种方法的一个关键优势是它将业务逻辑放在数据表中,而不是代码中,这通常更易于维护和扩展。

于 2009-11-05T19:30:33.993 回答