[英]how to fetch same record multiple time based on date conditions in mysql?
[英]MySQL statement to fetch a record based on multiple conditions through relational tables
我正在生成一个查询,该查询返回一组满足下面发布的所有条件的配置文件
我在 Ruby 中像这样接收数据,然后根据内容进行动态 MySQL 查询 -
[{ attribute_id: 58, parent_profile_name: 'Douglas-Connelly' },
{ attribute_id: 26, parent_profile_name: 'Brekke LLC' },
{ attribute_id: 35, val: 'Asa' },
{ attribute_id: 38, val: 'Stanton' }]
这些是数据库的当前内容
profile_attribute_values
profile_id attribute_id parent_profile_id val
6 58 2
6 26 5
6 35 nil 'Asa'
6 38 nil 'Stanton'
profile
id name
2 Douglas-Connelly
5 Brekke LLC
6 nil
我需要返回满足所有条件的所有配置文件 - 与profile_attribute_values相关的配置文件,其中 attribute_id 是 x,val 是 y,并且其中 attribute_id 是 x,并且 parent_profile name = y
我目前拥有的
SELECT * FROM
(SELECT P2. *
FROM profile_attribute_values PAV
INNER JOIN profiles P1 ON P1.id = PAV.parent_profile_id
INNER JOIN profiles P2 ON P2.id = PAV.profile_id
WHERE (PAV.ne_attribute_id = '58' AND P1.`name` = 'Douglas-Connelly')
) A,
(SELECT P1. *
FROM profiles P1
INNER JOIN profile_attribute_values PAV ON P1.id = PAV.profile_id
INNER JOIN profile_attribute_values PAV2 ON P1.id = PAV2.profile_id
WHERE (PAV.ne_attribute_id = '35' AND PAV.val = 'ASA')
AND (PAV2.ne_attribute_id = '38' AND PAV2.val = 'Stanton')
) B
WHERE A.id = B.id
这将返回
profile
id name
6 nil
这正是我想要的,虽然棘手的部分是我需要 attribute_id 26 和 parent_profile_name: 'Brekke LLC' 的第二个 parent_profile 条件
我知道这行不通,但我需要它来做这样的事情
SELECT * FROM
(SELECT P2. *
FROM profile_attribute_values PAV
INNER JOIN profiles P1 ON P1.id = PAV.parent_profile_id
INNER JOIN profiles P2 ON P2.id = PAV.profile_id
WHERE (PAV.ne_attribute_id = '58' AND P1.`name` = 'Douglas-Connelly')
AND (PAV.ne_attribute_id = '26' AND P1.`name` = 'Brekke LLC')
) A,
.....
我正在动态生成 SQL 语句,所以我真的需要它尽可能干净。 我一般都使用 ruby 活动记录,所以当涉及到 SQL 语句时,我有点幼稚。 谢谢!
更新
好的,我找到了一个很好的解决方案来生成我需要的动态查询,对数据库进行一次调用。 这是完成的课
class ProfileSearch
def initialize(params, args = {})
@attr_vals = params
@options = args
filter_attrs
end
attr_accessor :parent_attrs, :string_attrs
def search
Profile.joins(generate_query)
end
def generate_query
q = ''
q << parents_query
q << attr_vals_query
end
def parents_query
str = ''
parent_attrs.each_with_index do |pa, i|
str << "INNER JOIN profile_attribute_values PAVP#{i} ON profiles.id = PAVP#{i}.profile_id "\
"AND PAVP#{i}.ne_attribute_id = #{pa} "\
"INNER JOIN profiles PP#{i} ON PP#{i}.id = PAVP#{i}.parent_profile_id "\
"AND PP#{i}.`name` = '#{@attr_vals[pa.to_s]}' "
end
str
end
def attr_vals_query
str = ''
string_attrs.each_with_index do |a, i|
str << "INNER JOIN profile_attribute_values PAVS#{i} ON profiles.id = PAVS#{i}.profile_id "\
"AND PAVS#{i}.ne_attribute_id = #{a} AND PAVS#{i}.val = '#{@attr_vals[a.to_s]}' "
end
str
end
def filter_attrs
ne = NeAttribute.find(@attr_vals.keys)
self.parent_attrs = ne.select{ |x| x.parent_profile)_attr? }.map(&:id)
self.string_attrs = ne.select{ |x| x.string_attr? }.map(&:id)
end
end
您需要了解的第一件事是joins
。
像这样使用它:
relation_1 = ProfileAttributeValue.joins("
INNER JOIN profiles P1 ON P1.id = PAV.parent_profile_id
INNER JOIN profiles P2 ON P2.id = PAV.profile_id
").where(..).pluck(:id)
relation_2 = ProfileAttributeValue.joins...where...pluck(:id)
关系_1 和关系_2 尚未运行。 它们是 ActiveRecord 关系。
我喜欢以下技巧:
ProfileAttributeValue.where(["profile_attribute_values.id in (?) or profile_attribute_values.id in (?)]", relation_1, relation_2)
同样,这只是一个 activerecord 关系。 如果好奇,请调用to_sql
。 添加更多.where
或其他内容,当运行时,它将是对数据库的单个查询。
发布我所做的作为答案,以防万一有人错过了上面的内容。 这实质上创建了一个单一的连接查询,允许我提取所需的确切数据。 生成的查询如下所示 -
SELECT `profiles`.*
FROM `profiles`
INNER JOIN profile_attribute_values PAVP0 ON profiles.id = PAVP0.profile_id
AND PAVP0.ne_attribute_id = 26
INNER JOIN profiles PP0 ON PP0.id = PAVP0.parent_profile_id
AND PP0.`name` = 'Brekke LLC'
INNER JOIN profile_attribute_values PAVP1 ON profiles.id = PAVP1.profile_id
AND PAVP1.ne_attribute_id = 58
INNER JOIN profiles PP1 ON PP1.id = PAVP1.parent_profile_id
AND PP1.`name` = 'Douglas-Connelly'
INNER JOIN profile_attribute_values PAVS0 ON profiles.id = PAVS0.profile_id
AND PAVS0.ne_attribute_id = 35 AND PAVS0.val = 'Asa'
INNER JOIN profile_attribute_values PAVS1 ON profiles.id = PAVS1.profile_id
AND PAVS1.ne_attribute_id = 38 AND PAVS1.val = 'Stanton'
这是生成它的类
class ProfileSearch
def initialize(params, args = {})
@attr_vals = params
@options = args
filter_attrs
end
attr_accessor :parent_attrs, :string_attrs
def search
Profile.joins(generate_query)
end
def generate_query
q = ''
q << parents_query
q << attr_vals_query
end
def parents_query
str = ''
parent_attrs.each_with_index do |pa, i|
str << "INNER JOIN profile_attribute_values PAVP#{i} ON profiles.id = PAVP#{i}.profile_id "\
"AND PAVP#{i}.ne_attribute_id = #{pa} "\
"INNER JOIN profiles PP#{i} ON PP#{i}.id = PAVP#{i}.parent_profile_id "\
"AND PP#{i}.`name` = '#{@attr_vals[pa.to_s]}' "
end
str
end
def attr_vals_query
str = ''
string_attrs.each_with_index do |a, i|
str << "INNER JOIN profile_attribute_values PAVS#{i} ON profiles.id = PAVS#{i}.profile_id "\
"AND PAVS#{i}.ne_attribute_id = #{a} AND PAVS#{i}.val = '#{@attr_vals[a.to_s]}' "
end
str
end
def filter_attrs
ne = NeAttribute.find(@attr_vals.keys)
self.parent_attrs = ne.select{ |x| x.parent_profile)_attr? }.map(&:id)
self.string_attrs = ne.select{ |x| x.string_attr? }.map(&:id)
end
end
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.