【问题标题】:'In' clause in SQL server with multiple columnsSQL Server 中的“In”子句具有多列
【发布时间】:2016-05-13 15:39:11
【问题描述】:

我有一个组件可以根据提供的键从数据库中检索数据。 但是,我希望我的 java 应用程序能够获取单个数据库命中中所有键的所有数据,以加快处理速度。 当我只有一个键时,我可以使用 'in' 子句。

在处理多个键时,我可以在 oracle 中使用以下查询

SELECT * FROM <table_name> 
where (value_type,CODE1) IN (('I','COMM'),('I','CORE'));

类似于写作

SELECT * FROM <table_name> 
where value_type = 1 and CODE1 = 'COMM' 

SELECT * FROM <table_name> 
where value_type = 1 and CODE1 = 'CORE' 

一起

但是,上面使用“in”子句的这个概念在“SQL server”中给出了以下错误

ERROR:An expression of non-boolean type specified in a context where a condition is expected, near ','.

请告知他们是否有任何方法可以在 SQL Server 中实现相同的功能。

【问题讨论】:

  • 试试这个:SELECT * FROM where value_type = 1 and CODE1 IN ( 'COMM' , 'CORE' )
  • 谢谢。但实际上我正在寻找可以在两个键中处理多个值的东西。所以在实际情况下,我的第一个键值不会总是'1',可以是任何东西。并为两个键使用 IN 将搜索笛卡尔积,这不会是正确的输出。
  • 您的第一个示例是一个非标准的 Oracle 扩展。如果您想要在 Oracle 以外的其他数据库上运行的 SQL,则需要单独的“AND”子句,而不是元组:docs.oracle.com/cd/E12032_01/doc/epm.921/html_techref/maxl/dml/…
  • @paulsm4 第一个示例适用于 Postgres 和 MySQL(非常肯定)。

标签: sql sql-server oracle


【解决方案1】:

SQL Server 中不存在此语法。使用AndOr 的组合。

SELECT * 
FROM <table_name> 
WHERE 
  (value_type = 1 and CODE1 = 'COMM')
  OR (value_type = 1 and CODE1 = 'CORE') 

(在这种情况下,您可以缩短它,因为 value_type 与两种组合中的相同值进行比较。我只是想展示在 oracle 中具有多个字段的模式。)


将 IN 与子查询一起使用时,您需要将其改写为:

甲骨文:

SELECT * 
FROM foo 
WHERE 
  (value_type, CODE1) IN (
    SELECT type, code 
    FROM bar
    WHERE <some conditions>)

SQL 服务器:

SELECT * 
FROM foo 
WHERE 
  EXISTS (
    SELECT * 
    FROM bar 
    WHERE <some conditions>
      AND foo.type_code = bar.type 
      AND foo.CODE1 = bar.code)

根据具体情况,还有其他方法可以做到这一点,例如内部连接等。

【讨论】:

  • 感谢斯特凡。我有数百万条数据记录进入我的 java 应用程序,所以这样做对 Java 来说可能有点忙和耗时。但猜想他们没有其他办法,所以必须检查一下。感谢您的帮助。
  • 这不允许您传递值列表(元组)以使其成为动态的。这对于像他的第一个示例(适用于其他数据库)这样的仅两种组合非常严格。
【解决方案2】:

通常你不能这样做,但可以使用以下技术。

SELECT * FROM <table_name> 
where (value_type+'/'+CODE1) IN (('I'+'/'+'COMM'),('I'+'/'+'CORE'));

【讨论】:

  • 请注意,这将丢失您在表上的所有索引,除非您碰巧专门为此模式编制索引。
  • 我喜欢这个解决方案的简单性。但请注意,如果删除分隔符,可能会导致错误:'ab' + 'c' = 'a'+'bc'。
【解决方案3】:

如果您要检查的元组少于 1000 个,并且您使用的是 SQL Server 2008+,则可以使用 table values constructor,并对其执行联接。您最多只能在表值构造函数中指定 1000 行,因此有 1000 个元组的限制。以下是它在您的情况下的样子:

SELECT <table_name>.* FROM <table_name> 
JOIN ( VALUES
    ('I', 'COMM'),
    ('I', 'CORE')
) AS MyTable(a, b) ON a = value_type AND b = CODE1;

这只是一个好主意,如果您的值列表将是唯一的,否则您将获得重复的值。我不确定它的性能与使用许多 AND 和 OR 相比如何,但在我看来,SQL 查询至少看起来更清晰。

您也可以编写此代码以使用 EXIST 而不是 JOIN。这可能具有不同的性能特征,如果您的值不是唯一的,它将避免产生重复结果的问题。可能值得在您的用例上同时尝试 EXIST 和 JOIN 以查看更适合的方法。这是 EXIST 的外观,

SELECT * FROM <table_name> 
WHERE EXISTS (
    SELECT 1
    FROM (
        VALUES
            ('I', 'COMM'),
            ('I', 'CORE')
    ) AS MyTable(a, b)
    WHERE a = value_type AND b = CODE1
);

总之,我认为最好的选择是创建一个临时表并针对它进行查询。但有时这是不可能的,例如您的用户缺乏创建临时表的权限,然后使用表值构造函数可能是您的最佳选择。使用 EXIST 或 JOIN,具体取决于哪个可以为您提供更好的数据库性能。

【讨论】:

    【解决方案4】:

    更好的解决方案是避免硬编码您的值,然后将其放入临时或持久表中:

    CREATE TABLE #t (ValueType VARCHAR(16), Code VARCHAR(16))
    
    INSERT INTO #t VALUES ('I','COMM'),('I','CORE')
    
    SELECT DT. * 
    FROM <table_name> DT 
    JOIN #t T ON T.ValueType = DT.ValueType AND T.Code = DT.Code
    

    因此,您可以避免在代码中存储数据(持久表版本),并允许轻松修改过滤器(无需更改代码)。

    【讨论】:

      【解决方案5】:

      我想你可以试试这个,同时结合andor

      SELECT 
        * 
      FROM 
        <table_name> 
      WHERE 
        value_type = 1 
        AND (CODE1 = 'COMM' OR CODE1 = 'CORE')
      

      【讨论】:

        【解决方案6】:

        您可以做的是将列“加入”为字符串,并将您的值也组合为字符串传递。

        where (cast(column1 as text) ||','|| cast(column2 as text)) in (?1)
        

        另一种方法是做多个ands和ors。

        【讨论】:

          【解决方案7】:

          我在 MS SQL 中遇到了类似的问题,但略有不同。也许它会在未来对某人有所帮助,就我而言,我找到了这个解决方案(不是完整的代码,只是示例):

          SELECT Table1.Campaign
                ,Table1.Coupon
            FROM [CRM].[dbo].[Coupons] AS Table1 
            INNER JOIN [CRM].[dbo].[Coupons] AS Table2 ON Table1.Campaign = Table2.Campaign AND Table1.Coupon = Table2.Coupon
            WHERE Table1.Coupon IN ('0000000001', '0000000002') AND Table2.Campaign IN ('XXX000000001', 'XYX000000001')
          

          当然,关于表中的优惠券和活动,我有快速搜索的索引。

          【讨论】:

            【解决方案8】:

            在 MS Sql 中计算

            SELECT * FROM <table_name> 
            where value_type + '|' + CODE1 IN ('I|COMM', 'I|CORE');
            

            【讨论】:

              猜你喜欢
              • 2011-05-26
              • 2012-10-13
              • 2012-11-15
              • 1970-01-01
              • 2021-05-11
              • 1970-01-01
              • 2014-02-06
              • 2013-06-25
              • 1970-01-01
              相关资源
              最近更新 更多