【问题标题】:Distinct Union on Select. Errors on ntext data type选择上的不同联合。 ntext 数据类型错误
【发布时间】:2012-01-13 12:03:21
【问题描述】:

我在 SQL 方面很无用,但我发现自己不得不为非常简单的关键词搜索编写一个存储过程。

我正在尝试对名称进行简单的选择 - 使用 %keyword%- 然后在描述上进行另一个选择 - 相同的关键字 - 并加入(联合)这 2 个选择。

但是,我得到了错误:

The ntext data type cannot be selected as DISTINCT because it is not comparable.

我尝试使用 UNION ALL,但在某些情况下会返回重复的行(取决于关键字/短语)。

我也尝试过使用临时表并在其上选择 distinct,但这就是我真正感到困惑的地方。

规则:

  • 我无法更改数据类型
  • 我需要“名称”上选择的行位于“描述”上选择的行上方
  • 我只能使用 1 个存储过程,并且无法更改数据适配器,因为我将它插入到我无法控制的系统中。

更多信息:

表格列(我使用的重要的 2 个是名称和描述):

ProductId   int
Name    varchar(255)
Introduction    varchar(255)
Description ntext
Material    ntext
Colour  varchar(255)
Active  bit
Dimensions  varchar(255)
Photo   varchar(255)
Price   decimal(10, 2)
DisplayOrder    int
ProductReference    varchar(255)
CategoryId  int
FriendlyURL varchar(1000)

SQL:

(SELECT        Products.ProductId, Name, Introduction, Description, Active, 
            Material, Colour, Dimensions, Photo, Price, DisplayOrder, FriendlyURL,
            ProductReference, Categories_Products_Lookup.CategoryId
FROM            Products INNER JOIN
                Categories_Products_Lookup ON 
                Products.ProductId = Categories_Products_Lookup.ProductId
WHERE           Active = 1 AND tProduct.Name like '%'+@Keyword+'%')
UNION
(SELECT        Products.ProductId, Name, Introduction, Description, Active, 
            Material, Colour, Dimensions, Photo, Price, DisplayOrder, FriendlyURL,
            ProductReference, Categories_Products_Lookup.CategoryId
FROM            ProductsINNER JOIN
                Categories_Products_Lookup ON 
                Products.ProductId = Categories_Products_Lookup.ProductId
WHERE           Active = 1 AND Products.Description like '%'+@Keyword+'%')

非常感谢任何帮助获取不同行的表。另外,作为外行向我解释会很棒。 :)

【问题讨论】:

  • 您使用的是哪个版本的 SQL Server?如果 2005+ 可以将列的数据类型更改为nvarchar(max)ntext 已弃用且难以使用。 nvarchar(max) 是它的替代品。还有一个具体原因为什么您在这里使用UNION 而不是or
  • 嗨,马丁,我使用的是 2008 R2。但是,我认为我无法更改数据类型。它有一个完整的系统在运行,我不知道它会对其他领域产生什么连锁反应。使用 OR 会做什么?我希望从这两个选择中获得结果,但让来自“名称”的选择排在首位。
  • 好吧,您发布的查询有点混乱和无效,因为一个分支在Where 中提到了tProduct,但在FROM 和另一个Products 中没有这样的表,但假设他们是同一张桌子。 WHERE Active = 1 AND (Products.Description like '%'+@Keyword+'%') or Products.Name like '%'+@Keyword+'%') 会做同样的事情,而不必扫描表并执行两次连接然后合并两个结果。
  • 抱歉,是的,tProduct 和 Products 表是相同的。我在发布前稍作编辑,错过了一些更改。刚刚测试了 OR - 结果正常,但顺序错误。我希望在“名称”中带有关键字的行高于 any 其他行。似乎按 ID 顺序产生结果。
  • 即使您进行了强制转换以使其正常工作,您的 UNION 查询也不会发生所需的排序。

标签: sql sql-server sql-server-2008-r2


【解决方案1】:

使用类似 'cast(Description as nvarchar(2000)) as Description' 代替 ntext 字段名称。

【讨论】:

  • 您好 Arvo,我尝试了您的建议,并用该 cast 语句替换了对 Description 的所有引用,但出现了相同的错误:The ntext data type cannot be selected as DISTINCT because it is not comparable
  • @Deadly 也将相同的转换应用于Material(以及UNION 操作中涉及的任何其他text 列)
  • 您好 Arvo,感谢您的回答。我确信它会起作用,但上面的那个提供了一个我能理解的解决方案。干杯。 :)
【解决方案2】:

此答案适用于像我这样不会遇到重复行问题的其他人。

UNION ALL 可能就是你想要的。

请参阅documentation for the UNION operator

【讨论】:

  • 完美解决方案!我没有重复的问题。
【解决方案3】:

来自 cmets。看来这就是你需要的。

SELECT Products.ProductId,
       Name,
       Introduction,
       Description,
       Active,
       Material,
       Colour,
       Dimensions,
       Photo,
       Price,
       DisplayOrder,
       FriendlyURL,
       ProductReference,
       Categories_Products_Lookup.CategoryId
FROM   Products
       INNER JOIN Categories_Products_Lookup
         ON Products.ProductId = Categories_Products_Lookup.ProductId
WHERE  Active = 1
       AND ( Products.Description like '%' + @Keyword + '%'
              or Products.Name like '%' + @Keyword + '%' )
ORDER  BY CASE
            WHEN Products.Name like '%' + @Keyword + '%' THEN 0
            ELSE 1
          END  

您可能需要考虑为此使用Full Text Search,因为带有前导通配符的搜索不能使用索引并且总是需要扫描所有行。

【讨论】:

  • 你是个天才!我想我可能会爱你! :D 非常感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-18
  • 1970-01-01
相关资源
最近更新 更多