Mysql问题:有没有类似IN ALL的查询?

发布于 2024-08-31 02:26:14 字数 1063 浏览 6 评论 0原文

例如这个查询:

SELECT `variants`.* 
  FROM `variants` INNER JOIN `variant_attributes` 
    ON variant_attributes.variant_id = variants.id 
 WHERE (variant_attributes.id IN ('2','5'))

Andvarianthas_manyvariant_attributes

我真正想做的是找到哪个变体同时具有 ID = 2 和 5 的两个变体属性。这对于 MySQL 来说可能吗?额外的问题,有没有一种快速的方法可以使用 Ruby on Rails(也许使用 SearchLogic)来做到这一点?

解决方案

谢谢Quassnoi 提供的查询,效果非常好。

为了在Rails上使用,我使用了下面的named_scope,我认为这对于初学者来说更容易理解。

基本上,named_scope 会返回 {:from =>; x,:条件=> y} 和上面的行用于设置 y 变量。

  named_scope :with_variant_attribute_values, lambda { |values|
    conditions = ["(
            SELECT  COUNT(*)
            FROM    `variant_attributes`
            WHERE   variant_attributes.variant_id = variants.id
                    AND variant_attributes.value IN (#{values.collect { |value| "?" }.join ", "})
            ) = ?
    "]
    conditions = conditions + values + [values.length]
    {
    :from => 'variants', 
    :conditions => conditions
  }}

For example this query:

SELECT `variants`.* 
  FROM `variants` INNER JOIN `variant_attributes` 
    ON variant_attributes.variant_id = variants.id 
 WHERE (variant_attributes.id IN ('2','5'))

And variant has_many variant_attributes

What I actually want to do is to find which variant has BOTH variant attributes with ID = 2 and 5. Is this possible with MySQL? Bonus Question, is there a quick way to do this with Ruby on Rails, perhaps with SearchLogic?

solution

Thank you Quassnoi for the query you provided, that worked perfectly.

To use on Rails, I used the named_scope below, I think this is simpler to understand for beginners.

Basically named_scope would return {:from => x, :conditions => y} and the lines above were used to setup the y variable.

  named_scope :with_variant_attribute_values, lambda { |values|
    conditions = ["(
            SELECT  COUNT(*)
            FROM    `variant_attributes`
            WHERE   variant_attributes.variant_id = variants.id
                    AND variant_attributes.value IN (#{values.collect { |value| "?" }.join ", "})
            ) = ?
    "]
    conditions = conditions + values + [values.length]
    {
    :from => 'variants', 
    :conditions => conditions
  }}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

苹果你个爱泡泡 2024-09-07 02:26:14

假设 variant_attributes (variant_id, id) 是唯一的:

SELECT  `variants`.*
FROM    `variants`
WHERE   (
        SELECT  COUNT(*)
        FROM    `variant_attributes`
        WHERE   variant_attributes.variant_id = variants.id
                AND variant_attributes.id IN ('2','5')
        ) = 2

Assiuming that variant_attributes (variant_id, id) is unique:

SELECT  `variants`.*
FROM    `variants`
WHERE   (
        SELECT  COUNT(*)
        FROM    `variant_attributes`
        WHERE   variant_attributes.variant_id = variants.id
                AND variant_attributes.id IN ('2','5')
        ) = 2
娇纵 2024-09-07 02:26:14

Quassnoi 发布了 mysql 查询,可以完成您想要的操作。下面是用于 Variant 模型的方法,它可以执行相同的操作。我正在采用两种方法,一种是如果 variant_attributes (variant_id, id) 是唯一的组合,另一种是如果它们不是

唯一的:

class Variant < ActiveRecord::Base
  has_many :variant_attributes
  named_scope :with_variant_attributes, lamda { |*ids|
     ids = ids.flatten
     if(ids.length>0)
       result = {:include => :variant_attributes}
       sql_params = {:length => ids.length,:ids => ids}
       result[:conditions] = ["(:length = (select count(*) from variant_attributes
                                          where id in (:ids))",sql_params]
       result
     else
       nil
     end
   }
end

非唯一

class Variant < ActiveRecord::Base
  has_many :variant_attributes
  named_scope :with_variant_attributes, lamda { |*ids|
     ids = ids.flatten
     if(ids.length>0)
       result = {:include => :variant_attributes}
       conditions = []
       sql_params = {}

       ids.each_with_index do |id,i|
         conditions << "( 1 = Select Count(*) from variant_attributes where id = :id#{i})"
         sql_params["id#{i}"] =  id
       end
       result[:conditions] = [ '(' + conditions.join(' AND ') + ')', sql_params]
       result
     else
       nil
     end
   }
end

可以通过以下方式使用:

# Returns all Variants with variant_attributes 1, 2, & 3
vars = Variant.with_variant_attributes(1,2,3) 

# Returns Variant 5 if it has attributes 3 & 5, or null if it doesn't
vars = Variant.with_variant_attributes(3,5).find_by_id(5)

#Returns Variants between 1 and 20 if that have an attribute of 2
vars = Variant.with_variant_attributes(2).find(:conditions => "id between 1 and 20")

#can accept a variable array of ids
my_ids = [3,5]
vars = Variant.with_variant_attributes(my_ids)

此代码没有没有经过测试。

Quassnoi has posted the mysql query that does what you would like. Here is a method for the Variant model that will do the equivalent. I'm doing two approaches, one if variant_attributes (variant_id, id) are a unique combination, and one if they aren't

Unique:

class Variant < ActiveRecord::Base
  has_many :variant_attributes
  named_scope :with_variant_attributes, lamda { |*ids|
     ids = ids.flatten
     if(ids.length>0)
       result = {:include => :variant_attributes}
       sql_params = {:length => ids.length,:ids => ids}
       result[:conditions] = ["(:length = (select count(*) from variant_attributes
                                          where id in (:ids))",sql_params]
       result
     else
       nil
     end
   }
end

Non Unique

class Variant < ActiveRecord::Base
  has_many :variant_attributes
  named_scope :with_variant_attributes, lamda { |*ids|
     ids = ids.flatten
     if(ids.length>0)
       result = {:include => :variant_attributes}
       conditions = []
       sql_params = {}

       ids.each_with_index do |id,i|
         conditions << "( 1 = Select Count(*) from variant_attributes where id = :id#{i})"
         sql_params["id#{i}"] =  id
       end
       result[:conditions] = [ '(' + conditions.join(' AND ') + ')', sql_params]
       result
     else
       nil
     end
   }
end

Which can be used in the following ways:

# Returns all Variants with variant_attributes 1, 2, & 3
vars = Variant.with_variant_attributes(1,2,3) 

# Returns Variant 5 if it has attributes 3 & 5, or null if it doesn't
vars = Variant.with_variant_attributes(3,5).find_by_id(5)

#Returns Variants between 1 and 20 if that have an attribute of 2
vars = Variant.with_variant_attributes(2).find(:conditions => "id between 1 and 20")

#can accept a variable array of ids
my_ids = [3,5]
vars = Variant.with_variant_attributes(my_ids)

This code hasn't been tested.

野却迷人 2024-09-07 02:26:14

我将为此创建一个命名范围:

class Variant < ActiveRecord::Base
  has_many    :variant_attributes

  named_scope :with_variant_attributes, lambda { |*ids| { 
            :joins => :variant_attributes, 
            :conditions => {:variant_attributes=>{:id=>ids}},
            :group => "variants.id",
            :having => "count(variants.id) = #{ids.size}"
            }
          }
end

现在您可以使用命名范围,如下所示:

Variant.with_variant_attributes(1,2)
Variant.with_variant_attributes(1,2,3,4)

I would create a named_scope for this:

class Variant < ActiveRecord::Base
  has_many    :variant_attributes

  named_scope :with_variant_attributes, lambda { |*ids| { 
            :joins => :variant_attributes, 
            :conditions => {:variant_attributes=>{:id=>ids}},
            :group => "variants.id",
            :having => "count(variants.id) = #{ids.size}"
            }
          }
end

Now you can use the named scope as follows:

Variant.with_variant_attributes(1,2)
Variant.with_variant_attributes(1,2,3,4)
樱花细雨 2024-09-07 02:26:14

感谢 Quassnoi 提供的查询,效果非常好。

为了在Rails上使用,我使用了下面的named_scope,我认为这对于初学者来说更容易理解。

基本上,named_scope 会返回 {:from =>; x,:条件=> y} 和上面的行用于设置 y 变量。

  named_scope :with_variant_attribute_values, lambda { |values|
    conditions = ["(
            SELECT  COUNT(*)
            FROM    `variant_attributes`
            WHERE   variant_attributes.variant_id = variants.id
                    AND variant_attributes.value IN (#{values.collect { |value| "?" }.join ", "})
            ) = ?
    "]
    conditions = conditions + values + [values.length]
    {
    :from => 'variants', 
    :conditions => conditions
  }}

Thank you Quassnoi for the query you provided, that worked perfectly.

To use on Rails, I used the named_scope below, I think this is simpler to understand for beginners.

Basically named_scope would return {:from => x, :conditions => y} and the lines above were used to setup the y variable.

  named_scope :with_variant_attribute_values, lambda { |values|
    conditions = ["(
            SELECT  COUNT(*)
            FROM    `variant_attributes`
            WHERE   variant_attributes.variant_id = variants.id
                    AND variant_attributes.value IN (#{values.collect { |value| "?" }.join ", "})
            ) = ?
    "]
    conditions = conditions + values + [values.length]
    {
    :from => 'variants', 
    :conditions => conditions
  }}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文