mysql选择哪里限制,加入哪里

时间:2013-01-20 16:42:06

标签: php mysql sql join

我有两个MySQL表

  • 产品(product_id,名称,类别)
  • products_sizes(product_id,size)

每件产品都有多种尺寸

我需要进行查询

  1. 根据类别和尺寸选择产品(如果设置了尺寸) - 例如category ='shoes'和size ='10'
  2. 它必须仍然返回产品的所有尺寸,但仅限于产品具有特定尺寸的尺寸
  3. 它必须同时将产品的结果限制为具有偏移的特定数字
  4. 我现在的查询如下。我工作,但不限制类别,只返回指定的一个尺寸(这里'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. 如果其中一个尺寸等于指定尺寸
    3. ,则返回每个产品的所有尺寸

      ...但是我仍然需要将结果限制在一定数量的产品中。如果我在查询的最后添加LIMIT $ limit,它将限制返回的大小数量而不是产品数量...感谢输入。

4 个答案:

答案 0 :(得分: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

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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

  1. 每个尺寸一排但限于10种不同的产品
  2. 10行 - 每个产品一个,包含逗号分隔大小的列
  3. 两个结果集,将在PHP中组合:
    • 10个产品
    • 相关尺寸
  4. 对于每种格式,您都需要以某种方式返回符合您条件的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-loop中:

    $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 |
    

    演示:

答案 3 :(得分:-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

您对符合特定条件的产品感兴趣,因此这是您选择的主要表格。

您想知道该产品的尺寸,将产品尺寸加入产品。

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