【问题标题】:Microsoft SQL Server Management Studio Rewrites my query incorrectlyMicrosoft SQL Server Management Studio 错误地重写了我的查询
【发布时间】:2014-04-29 09:38:08
【问题描述】:

我正在尝试在 Microsoft SQL Server Management Studio 2008 R2 中创建一个简单的视图。我尝试使用 Views > New View Designer 以及直接在查询构建器中键入 CREATE VIEW 命令,但无论我如何创建它,工作室都会使我的查询格式错误。

这里是源查询。特别注意 WHERE 子句:

 SELECT RTRIM(Orders.ITEMNUMBER) AS ItemNumber, 
        Orders.Type, 
        Orders.Quantity, 
        Orders.OrderNumber, 
        OrderDetails.SaleDate, 
        OrderLineItems.ReturnType,
        OrderLineItems.Action,
        OrderLineItems.Restock,
        OrderLineItems.Return
 FROM Orders 
 INNER JOIN OrderDetails ON Orders.Type = OrderDetails.Type 
 AND Orders.OrderNumber = OrderDetails.OrderNumber 
 INNER JOIN OrderLineItems ON Orders.OrderNumber = OrderLineItems.OrderNumber
 WHERE (OrderLineItems.Type = 'INVOICE' AND Orders.Type='3') OR 
       (OrderLineItems.Type = 'RETURN' AND Orders.Type='4')

但是,无论如何,SQL Server Management Studio 都会将查询错误地格式化为:

 SELECT RTRIM(Orders.ITEMNUMBER) AS ItemNumber, 
        Orders.Type, 
        Orders.Quantity, 
        Orders.OrderNumber, 
        OrderDetails.SaleDate, 
        OrderLineItems.ReturnType,
        OrderLineItems.Action,
        OrderLineItems.Restock,
        OrderLineItems.Return
 FROM Orders 
 INNER JOIN OrderDetails ON Orders.Type = OrderDetails.Type 
 AND Orders.OrderNumber = OrderDetails.OrderNumber 
 INNER JOIN OrderLineItems ON Orders.OrderNumber = OrderLineItems.OrderNumber
 WHERE (OrderLineItems.Type = 'INVOICE') AND (Orders.Type='3') OR 
       (OrderLineItems.Type = 'RETURN') AND (Orders.Type='4')

看,不同之处在于我想提取 OrderLineItems.Type 为 INVOICE 且 Orders.Type 为 3 或 OrderLineItems.Type 为 RETURN 且 Orders.Type 为 4 的行。它为我重写的查询弄乱了括号- 它不允许我在 OR 子句的两侧放置两个 AND 子句。

有没有办法绕过微软的查询重写器?或者即使括号没有正确分隔两个 AND 子句,上述重写的查询是否仍能被正确解释?

正如我所提到的,我已经尝试在“新查询”视图中使用直接 CREATE 查询来创建它,但它最终仍然格式错误。

感谢您的帮助。

编辑/结论

所以上面的两个查询在逻辑上是等价的。 MS SQL 的操作顺序导致它首先评估每个 AND 语句,然后最后检查 OR 语句。括号虽然很清楚,但没有必要。

【问题讨论】:

  • 也许通过添加inner和outer()可以绕过这个问题。这肯定是奇怪的行为。 (OrderLineItems.Type = 'INVOICE' AND Orders.Type='3') OR (OrderLineItems.Type = 'RETURN' AND Orders.Type='4') 变为 ((OrderLineItems.Type = 'INVOICE') AND (Orders.Type='3')) OR ((OrderLineItems.Type = 'RETURN') AND (Orders.Type='4'))
  • 我确实尝试过,在每个部分周围添加额外的括号,例如 ((a=b) AND (c=d)) OR ((e=f) AND (g=h)) 但作为我一提交,查询生成器就会恢复为 (a=b) AND (c=d) OR (e=f) AND (g=h) ... 似乎无法理解。跨度>
  • 我不得不玩弄引擎。引擎可能会处理这个给你想要的结果。查看顺序,引擎可能正在正确执行此操作。 (行类型和订单类型)或(行类型和订单类型)你得到不正确的结果吗?
  • 奇怪的是,引擎似乎是正确的,由于执行的先行者stackoverflow.com/questions/1241142/… AND 先胜然后 OR。
  • 哦,哇,好吧 - 这看起来很奇怪,但我想这是因为我习惯于更明确地使用括号而不是依赖于操作顺序,这可能因语言而异。我将仔细研究这些结果,看看它们是否真的正确。谢谢你。

标签: sql sql-server sql-server-2008 ssms


【解决方案1】:

可能听起来很傻,但是您是否尝试过顺其自然,并在纠正后将括号括起来?由于它坚持隔离每个条件......

WHERE ((OrderLineItems.Type = 'INVOICE') AND (Orders.Type='3')) 或 (((OrderLineItems.Type = 'RETURN') AND (Orders.Type='4'))

【讨论】:

  • 是的,确实如此。抱歉,我没有在问题中提到这一点,但它做同样的事情 - ((a=b) AND (c=d)) OR ((e=f) AND (g=h)) 总是恢复为 ( a=b) AND (c=d) OR (e=f) AND (g=h) ...如果在某处有一个选项可以禁用查询重写,那肯定是有意义的...寻找那个选项,但它似乎奇怪的缺席。
  • 好的。我有另一个理论。这可能是因为您的连接位置。因为您有一个连接指定与您的 AND 语句相同的对象,所以可能必须将它们隔离为条件。这意味着,您不能在一个地方加入它们,并在其他地方运行条件。
  • 好吧,WHERE 子句存在的原因基本上是因为我试图连接两个格式不同但含义相同的字段。即,在 OrderLineItems 中,Type 拼写为“INVOICE”或“RETURN”,但在 Orders 中,Type 由 3(发票)或 4(退货)表示。因此,WHERE 子句旨在充当替代 JOIN,因为我们实际上无法基于简单的相等性检查来连接它们。我认为 Type 仅用于在 WHERE 子句之前将 Orders 与 OrderDetails 连接,所以我不确定它是否会与 WHERE 子句冲突……我猜不确定。
  • 嗯。好的。如果你总是知道 3 是 Invoice 而 4 是 Return,你真的需要那个 AND 条件吗?如果您需要知道每个的结果,请将您的选择设置为返回 Orders.Type 的 CASE。 3 作为“发票”,4 作为“退货”。并将 OR 子句留在其中。
  • 我想我们已经在上面的 cmets 中找到了这个,但非常感谢您的帮助,durbnpoisn。因此,事实证明这两个语句在逻辑上是等价的,因为 MS SQL 的操作顺序首先解析两个 AND 语句,然后最后检查中间的 OR 语句。所以我为了自己的清楚而添加的括号毕竟是不必要的。微软说:不要质疑,拥抱它!哈哈
【解决方案2】:

在 SQL Server 下使用指关节会使您失去可读性。

您可以尝试使用 CTE 改进它:

with where_condition as 
(select 'INVOICE' OrderLineType, '3' OrderType union all 
 select 'RETURN', '4')

select * from <list of your tables>, where_condition
where OrderLineItems.Type = where_condition.OrderLineType and 
Orders.Type= where_condition.OrderType

很遗憾,SQL Server 还不支持(tuple) in (select ..) 语法。

【讨论】:

    猜你喜欢
    • 2013-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多