【问题标题】:SQL Exclude LIKE items from tableSQL 从表中排除 LIKE 项目
【发布时间】:2009-01-09 22:35:40
【问题描述】:

我试图弄清楚如何使用表 B 中的排除列表从表 A 中的 select 语句中排除项目。问题是我是根据字段的前缀排除的。

所以一个字段值可能是“FORD Muffler”并将它从我会做的基本查询中排除:

SELECT FieldName 
FROM TableName 
WHERE UPPER(ColumnName) NOT LIKE 'FORD%'

但要使用从不同表格中排除的值列表,我会使用子查询,例如:

SELECT FieldName 
FROM TableName 
WHERE UPPER(ColumnName) NOT IN (Select FieldName2 FROM TableName2)

问题在于它只排除完全匹配而不排除 LIKE 或通配符 (%)。

我怎样才能完成这项任务?重新设计表格不是一种选择,因为它是一个正在使用的现有表格。

编辑:对不起,我使用的是 SQL Server (2005)。

【问题讨论】:

  • Table2中的值是定长的还是可变的?
  • 它们可以是不同的长度。
  • Joel 给出了一个很好的答案,但我只想指出,必须寻找一个子字符串来比较表之间是数据库设计问题的一个大危险信号。我不知道具体情况,所以我不能说,但您可能需要查看它,记住一列应该只包含一个事实。

标签: sql subquery


【解决方案1】:

我认为这样做可以:

SELECT FieldName
FROM TableName
LEFT JOIN TableName2 ON UPPER(ColumnName) LIKE TableName2.FieldName2 + '%'
WHERE TableName2.FieldName2 IS NULL

【讨论】:

  • 为什么你有 WHERE TableName2.FieldName2 IS NULL?这似乎违背了加入的目的。
  • 它的存在是因为他只想要没有匹配项的记录。因为它是左外连接,所以在应用 where 过滤器时,第一个表中的记录仍然可用。第二个表中的记录只有空值。
  • 换句话说,INNER 连接将返回与他想要的完全相反的结果:第一个表与第二个表相同的记录。没有 where 子句的 OUTER 连接将返回 BOTH: 匹配且不匹配的记录。然后添加这个 where 子句,我们只返回不匹配的记录。
【解决方案2】:

不知道这会有多有效,但它应该可以工作:

SELECT FieldName 
FROM TableName t1
WHERE NOT EXISTS (
    SELECT *
    FROM TableName2 t2
    WHERE t1.FieldName LIKE t2.FieldName2 + '%'
)

【讨论】:

  • 我会将其更改为“select 1”而不是“select *”,因为没有必要检索所有字段,因为您不使用它们。
  • 加入通常更快,但当然你总是需要配置文件才能确定。
  • 查询优化器无论如何都会优化它。
  • @Garry 我自己在“EXISTS”子查询中总是使用“1”,但认为这可能会让人们在这个答案中感到困惑。无论如何,我不相信它会对更高级的 SQL 引擎产生影响。
  • @recursive 应该,但并非总是如此。在这种情况下,重写很简单,但它们可能会变得相当麻烦,因为任何任意查询都可以在“exists”内部,并且不清楚如何计算存在列表与连接的成本。所以优化器可能看不到这一点。尤其是mysql优化器...
【解决方案3】:
SELECT * FROM table_A 
LEFT OUTER JOIN table_B 
    ON (locate(table_b.column, UPPER(table_a.column)) == 1)
WHERE table_b.column IS NULL

【讨论】:

    猜你喜欢
    • 2014-10-09
    • 2013-06-10
    • 2014-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-12
    • 1970-01-01
    相关资源
    最近更新 更多