在MySQL中选择子查询

时间:2010-01-26 07:46:45

标签: mysql

我知道这不是创建表格的好习惯,所以请先把这些东西放在一边。

我有一张桌子,比如桌子A和桌子B

Table A :
| ID | fk_tableB_ID | title
-------------------------
| 10 | 1,2          | title 1
| 11 | 3            | title 2

Table B :
| ID | category
---------------
| 1  | cat1
| 2  | cat2
| 3  | cat3

我尝试了这个查询:

SELECT
    a.ID,
    a.title,
    (
        SELECT
            group_concat(b.category)
        FROM
            tableB B
        WHERE
            B.ID IN (a.fk_tableB_ID)
    ) as category
FROM
    tableA a

它返回:

| ID | category  | title
-----------------------
| 10 | cat1      | title1
| 11 | cat3      | title2            

但这不是我想要的。我想要的是

| ID | category  | title
-----------------------
| 10 | cat1,cat2 | title1
| 11 | cat3      | title2

请帮忙,什么是正确的mysql查询代码,以便我可以获得上面的表。 Thx提前

5 个答案:

答案 0 :(得分:0)

更好的方法是在中间放一个叫做'a_has_category'的桌子

Table a :
| ID | title
---------------
| 10 | title 1
| 11 | title 2

Table category :
| ID | category
---------------
| 1  | cat1
| 2  | cat2
| 3  | cat3

Table a_has_Category :
| ID | fk_a | fk_category
---------------
| 1  | 10   | 1
| 2  | 10   | 1
| 3  | 11   | 2

然后使用几个INNER JOINS构建您的查询

SELECT a.title, B.category FROM a
INNER JOIN a_has_category
ON fk_a = a_ID
INNER JOIN category
ON fk_category = category_ID

返回结果后,使用PHP的IMPLODE函数将类别连接成一个带逗号的字符串。

答案 1 :(得分:0)

是的,如果您在一个单元格中存储多个值,那么它几乎是如何工作的。省去麻烦并设计你的表,这样每行只有一个fk_tableB_ID。您可以将值组合到您选择的编程语言中的一行,因为它在MySQL中是不可行的。

这样的事情对你有用:

Table A :
| ID | page_ID | fk_tableB_ID | title
-------------------------
| 7  | 10      | 1            | title 1
| 8  | 10      | 2            | title 1
| 9  | 11      | 3            | title 2

Table B :
| ID | category
---------------
| 1  | cat1
| 2  | cat2
| 3  | cat3

您的查询将大大简化:

SELECT
    a.page_ID, 
    b.category, 
    a.title 
FROM 
    table_a a 
LEFT JOIN
    table_b b 
ON 
    a.fk_tableB_ID = b.ID

如果您碰巧使用PHP,请在那里进行组合。这应该有效:

$r = mysql_query('SELECT ... ');

$result = array();

while($row = mysql_fetch_assoc($r)) {
    $result[$row['page_ID']]['title'] = $row['title'];
    $result[$row['page_ID']]['categories'][] = $row['category'];
}

哪个应该是这样的:

Array
(
    [10] => Array
        (
            [title] => title 1
            [categories] => Array
                (
                    [0] => cat1
                    [1] => cat2
                )

        )

    [11] => Array
        (
            [title] => title_2
            [categories] => Array
                (
                    [0] => cat3
                )

        )    
)

如果你想使用那个数组来构建一个类似于你的例子的表,你可以使用它:

echo "| ID     | category            | title\n";
echo "----------------------------------------\n";
foreach($array as $page_ID => $row) {
    echo '| '.str_pad($page_ID, 7);
    echo '| '.str_pad(implode(',', $row['categories']), 20);
    echo '| '.$row['title']."\n";
}

哪个会输出:

| ID     | category            | title
----------------------------------------
| 10     | cat1,cat2           | title_1
| 11     | cat3                | title_2

这正是你想要的。当然你可能想要输出一个HTML表,但你明白了。

答案 2 :(得分:0)

我知道您不想听到这一点,但表格字段中的多个值不是一个好设计,特别是如果此字段引用另一个表格。
如果要创建多对多关系,则需要一个中间表:

Table A :
| ID | title
------------
| 10 | title 1
| 11 | title 2


Table B :
| ID | category
---------------
| 1  | cat1
| 2  | cat2
| 3  | cat3

Table A_B:
| fk_tableA_ID | fk_tableB_ID
-----------------------------
| 10           | 1
| 10           | 2
| 11           | 3

我不认为可以在单个查询中执行您想要的操作(可能在存储过程中),但让我们看看其他人提出的内容。

字段中只有一个值称为first normal form (1NF)。这是数据库优化的第一步。

答案 3 :(得分:0)

按照您尝试的方式执行此操作的问题是IN函数需要一个数组。如果你真的需要沿着这条路线走下去,你必须在字符串上运行一个函数来创建一个数组,然后在IN语句中使用它。

这里有一个例子http://forums.mysql.com/read.php?60,78776,242420#msg-242420

但我建议改为添加链接表。

答案 4 :(得分:0)

如前所述,在一列中有多个外键是糟糕的设计,你必须使用n:m表。 请参阅此表结构作为示例:(是的,我遗漏了一些索引:)

CREATE TABLE IF NOT EXISTS `a` (   `id` int(11) NOT NULL AUTO_INCREMENT,  `title` varchar(50) NOT NULL,   PRIMARY KEY (`id`) ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=5 ;

INSERT INTO `a` (`id`, `title`) VALUES (1, 'first row'), (2, 'second row'), (3, 'third row'), (4, 'fourth row');



CREATE TABLE IF NOT EXISTS `ab` (   `a_id` int(11) NOT NULL,   `b_id` int(11) NOT NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8;



INSERT INTO `ab` (`a_id`, `b_id`) VALUES (1, 1), (1, 2), (1, 4), (2, 5), (3, 5), (4, 6), (4, 5), (3, 6);


CREATE TABLE IF NOT EXISTS `b` (   `id` int(11) NOT NULL AUTO_INCREMENT,  `category` varchar(50) NOT NULL,   PRIMARY KEY (`id`) ) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=7 ;


INSERT INTO `b` (`id`, `category`) VALUES (1, 'Cat1'), (2, 'Cat2'), (3, 'Cat3'), (4, 'Cat4'), (5, 'Cat5'), (6, 'Cat6');

然后您可以使用此查询:

SELECT a.id, a.title, group_concat( b.category )
FROM a
LEFT JOIN ab ON a.id = ab.a_id
LEFT JOIN b ON b.id = ab.b_id
GROUP BY a.id;

导致:

id  title   group_concat(b.category)
1   first row   Cat4,Cat1,Cat2
2   second row  Cat5
3   third row   Cat5,Cat6
4   fourth row  Cat5,Cat6