LINUX.ORG.RU

sql выборку помогите осилить

 


0

2

Задача будто бы типичная, и во многих магазинах реализована, а как сделать не знаю. Есть таблица товаров и опций, связаны многие-ко-многим, habtm, через третью таблицу тобишь. И вот, допустим, нужно получить все товары, у которых опции id 1 и 2, сейчас sql такого вида: where ... in (1, 2), это опции и/или 1 и 2, а надо интерсекцию, пересечение, т.е чтобы опции у товара были и 1, и 2. Есть решение попроще, чтобы activerecord в рельсах справился? (бд postgres). Я про join, INNER JOIN который. Упрощенный запрос как сейчас: SELECT поля FROM products INNER JOIN options_products ON options_products.product_id = products.id INNER JOIN options ON options.id = options_products.id WHERE *всякие условия* AND options.id IN(1, 2)



Последнее исправление: Romaboy (всего исправлений: 3)

Я ничего не понял. Это ты так про join спросил или про подзапрос?

winlook38 ★★
()

Вот такая чепухня получилась (даже работает):

@checked_options.map!(&:to_i)
map = {}
ActiveRecord::Base.connection.select_rows("SELECT product_id, option_id FROM options_products WHERE option_id IN (#{@checked_options.join ','})").each do |row|
  product_id = row[0]
  m = map[product_id]
  if m
    m << row[1]
  else
    map[product_id] = [row[1]]
  end
end
count = @checked_options.count
ids = []
for product_id, option_ids in map
  ids << product_id if option_ids.count == count
end
@products = @products.where(id: ids)
2 запроса это нормально на это дело, хотя sql точно должен уметь такое.

Romaboy
() автор топика
Ответ на: комментарий от Romaboy

знатное спагетти! ты это уже через месяц не раскуришь

anonymous
()

Если правильно понял вопрос то:

SELECT prod.NAME FROM PRODUCT prod
INNER JOIN PRODUCT_TO_OPTION prod_to_opt ON (prod_to_opt.PRODUCT_ID = prod.ID)
INNER JOIN OPTION opt ON (opt.ID = prod_to_opt.OPTION_ID)
WHERE opt.name IN ('option1', 'option2')
GROUP BY prod.NAME
HAVING COUNT(DISTINCT(opt.name)) = 2;


Тестовый пример:
http://goo.gl/lQiZ6X
OnlineMagic
()
Ответ на: комментарий от OnlineMagic

Да, верно, этот sql делает то же, что и мое руби-спагетти выше, спасибо.

Romaboy
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.