SQL左连接多对多,只在左表中显示不同的ID

时间:2016-01-28 09:19:08

标签: php mysql join

表A

ID Name
1   Peter
2   Mary
3   John

表B

ID Event
1  eventA
2  eventB
3  eventC

表C

ID aID bID
1  1 1
2  1 3
3  2 1

我这样做

Select Distinct a.ID, b.ID
From tableA as a
Left Join tableC as c
On a.ID = c.aID
Left Join tableB as b
On c.bID = b.ID

显示

1 Peter eventA
1 Peter eventC

我想要输出如下

1 Peter eventA
        eventC

我怎么能这样做?非常感谢。

修订:

实际显示如下记录:

彼得1 eventA
eventC

从建议它工作正常,但我想添加隐藏显示功能。

功能ReverseDisplay(d){

if(document.getElementById(d).style.display ==“none”){

document.getElementById(d).style.display =“block”; }

else {document.getElementById(d).style.display =“none”; }

}

选择Distinct a.ID,b.ID,b.Event

从tableA作为

左连接tableC为c

在a.ID = c.aID

左连接tableB为b

在c.bID = b.ID

$lastId = "";
while($row = mysql_fetch_array($rs))
{   
    if ($lastId != $row[0]){
        echo "<a href='javascript:ReverseDisplay(" . ($row[0]) . ")'>" . $row[0] . "</a>";  
        echo urldecode($row[1])." ";    
        $lastId = $row[0];
        echo "<br/>";

        //id needs to be unique to match javascript function
        echo "<div id=" . ($row[0]) . " style='display:none;'>";
    }

    echo $row[2];   

    //that's the problem, </div> must print only one time when in the last loop of same a.id, but how???
    echo "</div>"   

}

如果我添加计数功能

选择Distinct a.ID,b.ID,b.Event,count(a.id)

从tableA作为

左连接tableC为c

在a.ID = c.aID

左连接tableB为b

在c.bID = b.ID

它只显示

彼得

eventA

//无法显示eventC

//仅循环一次

有人可以帮忙吗?我已经尝试了几天但失败了。非常感谢。

4 个答案:

答案 0 :(得分:3)

这是输出(HTML)格式问题,而不是SQL问题。 (理论上,您可以使用子查询,案例和空值构建一个非常复杂的查询,但实际上并不需要解决所有问题。)

如果执行此查询(请注意ORDER BY):

Select Distinct a.ID, a.Name, b.Event
From tableA as a
Left Join tableC as c
On a.ID = c.aID
Left Join tableB as b
On c.bID = b.ID
ORDER BY a.ID

然后在你的PHP中:

// I'm assuming you're using MySQLi in an OO fashion, but
// you can adjust this as needed.  Also, I'm missing out
// all the HTML (except a <BR>) - you can add in whatever
// HTML formatting you require as per your desired layout
$lastId = null; // remember the last person ID we had
while ($row = $result->fetch_assoc()) {
    if ($lastId != $row('ID') {
        // different person, so show their name:
        echo $row('Name');
        // and update $lastId 
        $lastId = $row('ID');
    }
    // show the event and move to the next line:
    echo $row('Event') . '<br>';
}

答案 1 :(得分:1)

我同意像这样的问题最好在表示层处理(例如一个简单的PHP循环),但只是为了好玩...

DROP TABLE IF EXISTS table_a;

CREATE TABLE table_a
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,name VARCHAR(20) NOT NULL UNIQUE
);

INSERT INTO table_a VALUES
(1,'Peter'),
(2,'Mary'),
(3,'John');

DROP TABLE IF EXISTS table_b;

CREATE TABLE table_b
(id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
,event VARCHAR(20) NOT NULL UNIQUE
);

INSERT INTO table_b VALUES
(1,'eventA'),
(2,'eventB'),
(3,'eventC');

DROP TABLE IF EXISTS table_c;

CREATE TABLE table_c
(a_id INT NOT NULL 
,b_id INT NOT NULL
,PRIMARY KEY(a_id,b_id)
);

INSERT INTO table_c VALUES
(1,1),
(1,3),
(2,1);

SELECT CASE WHEN a.id = @prev THEN '' ELSE a.id END a_id
     , CASE WHEN a.id = @prev THEN '' ELSE a.name END name
     , b.event
     , @prev := a.id
  FROM table_a a
  LEFT 
  JOIN table_c c
    ON c.a_id = a.id 
  LEFT
  JOIN table_b b
    ON b.id = c.b_id
 CROSS
  JOIN (SELECT @prev := null) vars
 ORDER 
    BY a.id, b.id; 

+------+-------+--------+---------------+
| a_id | name  | event  | @prev := a.id |
+------+-------+--------+---------------+
| 1    | Peter | eventA |             1 |
|      |       | eventC |             1 |
| 2    | Mary  | eventA |             2 |
| 3    | John  | NULL   |             3 |
+------+-------+--------+---------------+

答案 2 :(得分:0)

使用SQL无法实现这一目标。您必须在另一个级别上格式化该输出 - 显示输出时。但是,您可以使用SQL对检索到的记录进行排序,以减少PHP中的工作量。

因为我无法发表评论,所以我不建议经常使用PHP in_array()函数,因为与键控数组相比它很慢(你可以定义数组哪个键是你要搜索的值和值例如,如果是真的,那么只需通过索引和测试值来查看该数组。

$used_values = array()
$used_values[$value] = true;

试验:

if ($used_values[$value] === true).....

答案 3 :(得分:0)

在表示层执行此操作的另一个投票,但在单个SQL查询中以另一种方式执行此操作。

SELECT IF(b.id = min_bid OR min_bid IS NULL, a.id, ''), 
        IF(b.id = min_bid OR min_bid IS NULL, a.name, ''), 
        b.event
FROM table_a a
LEFT OUTER JOIN table_c c ON c.a_id = a.id 
LEFT OUTER JOIN table_b b ON b.id = c.b_id
LEFT OUTER JOIN
(
    SELECT a.id, MIN(b.id) AS min_bid
    FROM table_a a
    INNER JOIN table_c c ON c.a_id = a.id 
    INNER JOIN table_b b ON b.id = c.b_id
    GROUP BY a_id
) sub0
ON a.id = sub0.id
ORDER BY a.id, b.id