Как объединить запрос MySQL и подзапрос, когда есть несколько строк? - PullRequest
2 голосов
/ 02 ноября 2011

Меня всегда смущало, как объединить несколько запросов MySQL в один.Я вырывал свои волосы, пытаясь сделать следующее.Во-первых, я делаю запрос, чтобы получить результаты каждого поставщика и сколько продуктов у них есть:

SELECT vendor_name, COUNT(vendor_name) AS cnt FROM products GROUP BY vendor_name

Далее, так как я хочу, чтобы только те поставщики, у которых есть 10 или более продуктов, я делаю следующий PHP IFзаявление.Я не знаю, как включить это в вышеупомянутый SELECT, поэтому я делаю это через PHP.Я знаю, что это не самый лучший способ, но если вы не знаете лучший способ, вам нужно сделать это как-то так:

if ($database_row['cnt']>=10) {

В этом операторе IF я делаю запрос по каждому изпоставщики, у которых 10 или более продуктов:

SELECT id FROM products WHERE vendor_name="'.$database_row['vendor_name'].'"

, что дает мне идентификаторы каждого продукта для поставщиков, у которых есть как минимум 10 продуктов.Я знаю, что это небрежно, но это дает правильные результаты.Проблема в том, что мне нужно, чтобы все это было в одном запросе, и я не могу этого понять.Оба эти запроса находятся в одной и той же базе данных, и, похоже, это не такой сложный запрос, который на самом деле просто «показывает продукты тех поставщиков, у которых 10 или более продуктов».

Можно ли объединить вышесказанное в один запрос?Текущий полный код PHP / MySQL выглядит следующим образом:

$database_result = @mysql_query('SELECT vendor_name, COUNT(vendor_name) AS cnt FROM products GROUP BY vendor_name',$database_conn);
while($database_row = @mysql_fetch_array($database_result)) {
  if ($database_row['cnt']>=10) {
    $database_result2 = @mysql_query('SELECT id FROM products WHERE vendor_name="'.$database_row['vendor_name'].'"',$database_conn);
    // Process results
  }
}

Заранее спасибо!


Вот полный одиночный запрос, который теперь работает именно так, как я хотел.Может быть, есть умный способ оптимизировать запрос, но он работает и кажется достаточно быстрым.Спасибо всем!

SELECT
  p3.*
FROM
(
  SELECT
    p1.id,
    p1.department,
    p1.end_date,
    p1.quantity_sold,
    p2.vendor_name
  FROM
    products p1
  INNER JOIN
  (
    SELECT
      vendor_name
    FROM
      products
    GROUP BY
      vendor_name
    HAVING
      COUNT(*) >= 10
  ) p2
  ON
    p1.vendor_name = p2.vendor_name
  AND
    p1.sold_out = 0
  AND
    p1.end_date > NOW()
  ORDER BY
    p1.end_date DESC
) AS p3
GROUP BY
  p3.vendor_name
ORDER BY
  p3.quantity_sold DESC

Ответы [ 2 ]

3 голосов
/ 02 ноября 2011

Попробуйте это

SELECT 
    p1.id,
    p1.vendor_name 
FROM 
    products p1 
    INNER JOIN
    (
       SELECT 
          vendor_name,
          COUNT(vendor_name) as productCount 
       FROM 
          products 
       GROUP BY 
          vendor_name
       HAVING
          productCount >= 10
    ) p2
    ON p1.vendor_name=p2.vendor_name
1 голос
/ 02 ноября 2011

Добавить предложение having.

SELECT vendor_name, COUNT(vendor_name) AS cnt 
FROM products 
GROUP BY vendor_name
HAVING cnt >= 10

Наличие похоже на where, за исключением того, что оно оценивается после , все остальные пункты выполнены.
Это означает, что он может использовать агрегатные предложения.
Однако он не может использовать индекс.

Второй запрос пишется так:

SELECT id, vendorname FROM products p WHERE p.vendor_name IN
  (SELECT p2.vendor_name
   FROM products p2 
   GROUP BY p2.vendor_name
   HAVING COUNT(*) >= 10)

Внутреннее соединение может быть быстрее, см. Ответ @ liquorvicar.

...