从两个Mysql表中获取信息

时间:2012-02-21 06:52:13

标签: php mysql codeigniter

我正在使用Codeigniter,我正在尝试从两个表中调用信息:

产品: ID, 名称, 价钱, 描述, TYPEID

PRODUCT_TYPE: t类别, TNAME

我正在尝试从Product中提取所有信息,并使用Product.typeID匹配Product_Type表,并仅回退tName。大多数情况下,Product_Type表中至少有3行具有相同的typeID。例如:

产品1将是20美元的红色衬衫,从I型需要大,中,小。

我尝试用JOIN做这个,但它给了我需要的3种类型,但也复制了3次衬衫信息。

这是我的代码:

$this->db->select('product.id, product.name, product.price, product.description, product_type.tName');  
$this->db->from('product');
$this->db->where('perm_name', $id);
$this->db->join('product_type', 'product_type.tCategory = product.typeId', 'LEFT OUTER');
$query = $this->db->get(); 

非常感谢任何帮助。

编辑:

Array
(
    stdClass Object
        (
            [id] => 2
            [name] => Tshirt 1
            [price] => 20
            [description] => Awesome tshirt
            [tName] => 1
    )

)

Array
(
    [0] => stdClass Object
        (
            [tCategory] => 1
            [tName] => Small
    )

    [1] => stdClass Object
        (
            [tCategory] => 1
            [tName] => Medium
    )
    [2] => stdClass Object
        (
            [tCategory] => 1
            [tName] => Large
    )

)

1 个答案:

答案 0 :(得分:0)

要让产品行包含一列types,该列填充了第二个表的行,您可以连接两个表并使用group by:

SELECT 
    product.id, 
    max(product.name) as name, 
    max(product.price) as price, 
    max(product.description) as description, 
    group_concat(product_types.tName) as types

FROM
    product

LEFT JOIN
    product_type ON product.tName = product_types.tCategory

GROUP BY product.id

max(product.name)背后没有魔力。不允许在select子句中使用不在group by子句或聚合中的列。因为product.id是主键,所以我们每个product.id只能获得一个product.name,所以我们不关心3 product.name(来自3种类型的连接)中的哪一个被选中。他们都是一样的。我们甚至可以在select子句中写任何(product.name),但我不认为mysql支持这个。 =)

或进行相关的子查询〜

SELECT 
    product.id, 
    product.name, 
    product.price, 
    product.description, 
    (SELECT 
         group_concat(product_types.tName)
     FROM product_types
     WHERE product.tName = product_types.tCategory
     GROUP BY product_types.tCategory
    ) as types

FROM
    product

我建议使用第一个查询,因为mysql更容易优化。记录:我没有测试那些查询,所以他们可能需要一些调整。请告诉我。

编辑1:使用max()

的进一步说明

在以下查询中,我们不允许使用列name,因为我们只按列id分组。

SELECT
    id,
    name /* not allowed */

FROM
    product

GROUP BY id

我们只能选择group by - 子句中的列。我们也可以使用group by - 子句中不包含maxgroup_concat等聚合函数的列。

要解决此问题,我们只需将name列添加到group by - 子句

SELECT
    id,
    name /* ok because it's in group by */

FROM
    product

GROUP BY id, name

如果我们现在有name的不同值,我们将在结果中得到多个元组,例如:

对于product表(id,name)= {(1,Alice),(1,Bob)}我们得到结果

1, Alice
1, Bob

因为我们将两个列分组。

第二种方法是使用聚合函数,如max:

SELECT
    id,
    max(name) /* ok because it's aggregated */

FROM
    product

GROUP BY id

对于product表(id,name)= {(1,Alice),(1,Bob)}我们得到结果

1, Bob /* max(Alice,Bob) = Bob, because A < B */

在您的示例中,我假设列product.id是主键,因此是唯一的。这意味着name列中的id列中的值相等,我们不能有不同的值。 {(1, Alice), (1, Bob)}是不可能的,但也许{(1, Alice), (2, Bob)}。如果我们现在GROUP BY product.id,我们会为组中的每个元组获得product.name的值。但由于id确定了name,因此这些值都是相同的:

SELECT 
    product.id, 
    product.name, 
    product_type.tName,

FROM
    product

LEFT JOIN
    product_type ON product.tName = product_types.tCategory

将导致

(1, "White T-Shirt", Small),
(1, "White T-Shirt", Medium),
(1, "White T-Shirt", Large),
(2, "Black T-Shirt", Small),
(2, "Black T-Shirt", Medium),
(2, "Black T-Shirt", Large)

按product.id对其进行分组后,结果将如下所示

(1, F("White T-Shirt", "White T-Shirt", "White T-Shirt"), 
     G(Small, Medium, Large)),
(2, F("Black T-Shirt", "Black T-Shirt", "Black T-Shirt"), 
     G(Small, Medium, Large))

其中FGselect - 子句中使用的聚合函数。对于F,我们使用哪个值并不重要,它们都是相同的。所以我们只使用了max。对于g,我们使用group_concat将所有值连接在一起。

因此

F("White T-Shirt", "White T-Shirt", "White T-Shirt") = "White T-Shirt"
F("Black T-Shirt", "Black T-Shirt", "Black T-Shirt") = "Black T-Shirt"
G(Small, Medium, Large) = "Small, Medium, Large"

这将导致

(1, "White T-Shirt", "Small, Medium, Large"),
(2, "Black T-Shirt", "Small, Medium, Large")