关于子关联的多个条件的活动记录查询

时间:2018-03-15 15:01:56

标签: sql activerecord correlated-subquery

我需要有关子查询的帮助。

项目有很多方面。方面的属性为identifiercontent。方面identifiercontent用于提供过滤所显示项目的选项 - 例如,identifier可能是'颜色'而content'红色'或identifier为'尺寸',content为'10`

我想要一个返回项目

的查询
(label contains a search term) 

OR 
( has a facet with an identifier equal to one of 2 given values AND the content includes the search term) 

AND 
(it ALSO has ANOTHER facet whose identifier is equal to one of a number of some different values AND content equal to one of a number of yet more different values).

我试过的rails查询

rails query

items.joins(:facets)
  .where('items.label LIKE ? OR facets.identifier LIKE ?', "%#{search_term}%", "%#{search_term}%")
  .where('facets.identifier' => filter).where('facets.content' => value).uniq

转换为以下sql查询

SELECT DISTINCT (`items`.`id`) FROM `items` INNER JOIN `facets` ON 
`facets`.`item_id` = `items`.`id` AND `facets`.`identifier` IN ('summary', 'description') AND 
(items.label LIKE '%outing%' OR facets.content LIKE '%outing%') AND 
`facets`.`identifier` = 'color' AND `facets`.`content` IN 
('red')

这会返回一个空数组,因为我认为

之间存在冲突
`facets`.`identifier` IN ('summary', 'description')

`facets`.`identifier` = 'color'

如何编写一个基于多个方面返回项目的查询。是否可以将其写为活动记录而不是原始sql?

1 个答案:

答案 0 :(得分:0)

我已经确定了一种方法,虽然它不一定是最佳的:

 -- might use an existing calendar table to get those rows
create table yearmonth( ym int not null primary key);
insert into yearmonth values
(201701),
(201702),
(201703),
(201704),
(201705),
(201706),
(201707),
(201708),
(201709),
(201710),
(201711),
(201712);


with allLists as
 (  -- get all existing lists first
    -- (a table with those rows probably exists)
   select distinct List
   from Waitinglists
 )
, allCombinations as
 ( -- all year/month/list combinations
   select ym, list
   from yearmonth cross join allLists
 )
, WaitingYM as
 ( -- start/end date as YYYYMM
   select -- *
      list, 
      year(begindate)*100+month(begindate) as beginYM,
      coalesce(year(enddate)*100+month(enddate), 999999) as endYM
   from Waitinglists
 )
select a.ym, a.list, 
   count(w.list), -- current month

   -- difference to previous month
   count(w.list) -      
   lag(count(w.list))  -- previous month
   over (partition by a.list
         order by a.ym) 
from allCombinations as a
left join WaitingYM as w
  on a.list = w.list
 and ym between w.beginYM and w.endYM  -- expand to one row per year/month
group by a.list, a.ym
order by a.list, a.ym