5

我有以下两个 MySQL 表

  • 产品(product_id、名称、类别)
  • products_sizes (product_id, 尺寸)

每个产品都可以有多种尺寸

我需要查询

  1. 根据类别和尺寸选择产品(如果设置了尺寸) - 例如类别 = 'shoes' 和尺寸 = '10'
  2. 它仍然必须返回产品的所有尺寸,但前提是产品具有与其尺寸相同的特定尺寸
  3. 它必须同时将产品的结果限制在一定数量的偏移量

我现在有以下查询。我工作但不受类别限制,只返回指定的一种尺寸(此处为“10”) - 我需要所有尺寸,但仅适用于尺寸中有“10”的产品......

SELECT products.*
     , products_sizes.*
FROM (
   SELECT *
   FROM products 
   LIMIT $limit OFFSET $offset
   ) AS products
LEFT JOIN products_sizes 
   ON products.products_id = products_sizes.products_id 
WHERE products_sizes.size = 10

...如果我添加 WHERE category = 'something' 查询不返回任何内容...

SELECT products.*
     , products_sizes.*
FROM (
   SELECT * 
   FROM products 
   WHERE category = 'shoes' 
   LIMIT $limit OFFSET $offset
   ) AS products
LEFT JOIN products_sizes 
   ON products.products_id = products_sizes.products_id
WHERE products_sizes.size = 10

??

更新:越来越近...

阅读答案后,我现在有了这个:

SELECT *
FROM products AS p 
LEFT JOIN products_sizes AS s 
    ON p.product_id = s.product_id
    WHERE s.product_id 
        IN (SELECT product_id FROM s WHERE size = 10)
    AND p.category = 'shoes'

它满足了我最初的问题的前两个要求:

  1. 返回受类别和大小限制的结果
  2. 如果其中一个尺寸等于指定尺寸,则返回每个产品的所有尺寸

...但我仍然需要将结果限制为一定数量的产品。如果我在查询的最后放置一个 LIMIT $limit ,它将限制返回的尺寸数量而不是产品数量......感谢您的输入。

4

4 回答 4

1

您的主查询中的WHERE子句违背了您的目的LEFT JOIN,使其与INNER JOIN. 您的派生表很可能没有选择任何匹配的行(尺寸为 10 的鞋子)。

除非您的数据没有显示某些内容,否则您可以尝试以下操作:

SELECT products.*
     , products_sizes.*
FROM products 
JOIN products_sizes 
   ON products.products_id = products_sizes.products_id
WHERE products.category = 'shoes' 
   AND products_sizes.size = 10
LIMIT $limit OFFSET $offset
于 2013-01-20T17:00:28.120 回答
0

您的最终查询是绝对正确的。只需在子查询中使用限制,这将绑定产品的数量。

于 2013-12-02T09:55:41.310 回答
0

您可能需要至少三种结果格式:

  1. 每个尺寸一行,但仅限于 10 种不同的产品
  2. 10 行 - 每个产品一个,一列包含逗号分隔的尺寸
  3. 两个结果集,将在 PHP 中组合:
    • 10 个产品
    • 相关尺寸

对于每种格式,您需要以某种方式返回 10 种符合您条件的不同产品。

最有表现力的方式是使用 EXISTS 语句:

select p.*
from products p
where p.category = 'shoes'
and exists (
    select *
    from products_sizes ps
    where ps.product_id = p.product_id
      and ps.size = 10
)
order by p.product_id
limit $limit offset $offset

另一种方法是使用 JOIN:

select p.*
from products p
join products_sizes ps
  on ps.product_id = p.product_id
where p.category = 'shoes'
  and ps.size = 10
order by p.product_id
limit $limit offset $offset

由于其紧凑的代码,我将进一步使用第二个。但是你总是可以用 EXISTS 语句替换它。

1.

select p.*, ps.size
from (
    select p.*
    from products p
    join products_sizes ps
      on ps.product_id = p.product_id
    where p.category = 'shoes'
      and ps.size = 10
    order by p.product_id
    limit $limit offset $offset
) p
join products_sizes ps
  on ps.product_id = p.product_id
order by p.product_id, ps.size

2.

select p.*, group_concat(ps.size order by ps.size) as sizes
from products p
join products_sizes ps1
  on ps1.product_id = p.product_id
join products_sizes ps
  on ps.product_id = p.product_id
where p.category = 'shoes'
  and ps1.size = 10
group by p.product_id
order by p.product_id
limit $limit offset $offset

您可以使用explode()PHP 将字符串转换为数组:

$product->sizes = explode(',' $product->sizes);

3.

select p.*
from products p
join products_sizes ps
  on ps.product_id = p.product_id
where p.category = 'shoes'
  and ps.size = 10
limit $limit offset $offset

将结果存储在按产品 ID 索引的数组中。例如在 fetchAssoc 循环中:

$row->sizes = array();
$products[$row->product_id] = $row;

从结果中提取产品 ID:

$productIds = (',', array_keys($products));

获取相关尺寸;

select product_id, size
from products_sizes
where product_id in ($productIds)
order by product_id, size

在循环中链接尺寸

$products[$row->product_id]->sizes[] = $row->size;

给定以下示例数据

| product_id |   name | category | sizes |
|------------|--------|----------|-------|
|          1 | shoes1 |    shoes |   8,9 |
|          2 | shirt1 |   shirts | 10,11 |
|          3 | shoes2 |    shoes |  9,10 |
|          4 | shoes3 |    shoes | 10,11 |
|          5 | shoes4 |    shoes | 10,12 |

并使用LIMIT 2 OFFSET 0,结果将是:

1.

| product_id |   name | category | size |
|------------|--------|----------|------|
|          3 | shoes2 |    shoes |    9 |
|          3 | shoes2 |    shoes |   10 |
|          4 | shoes3 |    shoes |   10 |
|          4 | shoes3 |    shoes |   11 |

2.

| product_id |   name | category | sizes |
|------------|--------|----------|-------|
|          3 | shoes2 |    shoes |  9,10 |
|          4 | shoes3 |    shoes | 10,11 |

3.

| product_id |   name | category |
|------------|--------|----------|
|          3 | shoes2 |    shoes |
|          4 | shoes3 |    shoes |

| product_id | size |
|------------|------|
|          3 |    9 |
|          3 |   10 |
|          4 |   10 |
|          4 |   11 |

演示:

于 2016-11-05T22:06:03.723 回答
-1
SELECT *
FROM products AS p
LEFT JOIN products_sizes AS s ON p.product_id = s.product_id
WHERE p.product_id IN (SELECT product_id FROM products_sizes WHERE size = 10)
LIMIT 15

编辑(解释):

我正在考虑它并意识到您可能也想知道其中的原因:p

您对满足特定标准的产品感兴趣,因此这是您可供选择的主要表。

您想知道该产品的可用尺寸,将尺寸连接到产品。

您只对具有一定尺寸的产品感兴趣。运行子查询以查找具有该尺寸的产品。仅显示那些产品。

于 2013-01-20T17:02:48.500 回答