Php 将两个子表与一个不重复的父表联接 问题
我有三张桌子:人、电话和电子邮件。每个人都有一个唯一的ID,每个人可以有多个号码或多封电子邮件 它看起来是这样的:Php 将两个子表与一个不重复的父表联接 问题,php,mysql,sorting,join,Php,Mysql,Sorting,Join,我有三张桌子:人、电话和电子邮件。每个人都有一个唯一的ID,每个人可以有多个号码或多封电子邮件 它看起来是这样的: +---------+----------+ | ID | Name | +---------+----------+ | 5000003 | Amy | | 5000004 | George | | 5000005 | John | | 5000008 | Steven |
+---------+----------+
| ID | Name |
+---------+----------+
| 5000003 | Amy |
| 5000004 | George |
| 5000005 | John |
| 5000008 | Steven |
| 8000009 | Ashley |
+---------+----------+
+---------+-----------------+
| ID | Number |
+---------+-----------------+
| 5000005 | 5551234 |
| 5000005 | 5154324 |
| 5000008 | 2487312 |
| 8000009 | 7134584 |
| 5000008 | 8451384 |
+---------+-----------------+
+---------+------------------------------+
| ID | Email |
+---------+------------------------------+
| 5000005 | Smithley@goodmail.com.com |
| 5000005 | Smithley.j@gmail.com |
| 5000008 | Smithley@gmail.com |
| 5000008 | tech@goodmail.com |
| 5000008 | feler@campus.uni.com |
| 8000009 | Ashley.hill86@gmail.com |
| 5000004 | georgestanko@hotmail.com |
+---------+------------------------------+
SELECT People.Name, People.ID, Phones.Number, Emails.Email
FROM People
LEFT OUTER JOIN Phones ON People.ID = Phones.ID
LEFT OUTER JOIN Emails ON People.ID = Emails.ID
ORDER BY Name, ID, Number, Email;
+----------+---------+-----------------+------------------------------+
| Name | ID | Number | Email |
+----------+---------+-----------------+------------------------------+
| Steven | 5000008 | 8451384 | feler@campus.uni.com |
| Steven | 5000008 | 8451384 | Smithley@gmail.com |
| Steven | 5000008 | 8451384 | tech@goodmail.com |
| Steven | 5000008 | 24887312 | feler@campus.uni.com |
| Steven | 5000008 | 24887312 | Smithley@gmail.com |
| Steven | 5000008 | 24887312 | tech@goodmail.com |
| John | 5000005 | 5551234 | Smithley@goodmail.com |
| John | 5000005 | 5551234 | Smithley.j@gmail.com |
| John | 5000005 | 5154324 | Smithley@goodmail.com |
| John | 5000005 | 5154324 | Smithley.j@gmail.com |
| George | 5000004 | NULL | georgestanko@hotmail.com |
| Ashley | 8000009 | 7134584 | Ashley.hill86@gmail.com |
| Amy | 5000003 | NULL | NULL |
+----------+---------+-----------------+------------------------------+
我正在尝试将它们连接在一起,而不重复。当我尝试只加入与人的电子邮件或只加入与人的电话时,效果非常好。
SELECT People.Name, People.ID, Phones.Number
FROM People
LEFT OUTER JOIN Phones ON People.ID=Phones.ID
ORDER BY Name, ID, Number;
+----------+---------+-----------------+
| Name | ID | Number |
+----------+---------+-----------------+
| Steven | 5000008 | 8451384 |
| Steven | 5000008 | 24887312 |
| John | 5000005 | 5551234 |
| John | 5000005 | 5154324 |
| George | 5000004 | NULL |
| Ashley | 8000009 | 7134584 |
| Amy | 5000003 | NULL |
+----------+---------+-----------------+
SELECT People.Name, People.ID, Emails.Email
FROM People
LEFT OUTER JOIN Emails ON People.ID=Emails.ID
ORDER BY Name, ID, Email;
+----------+---------+------------------------------+
| Name | ID | Email |
+----------+---------+------------------------------+
| Steven | 5000008 | Smithley@gmail.com |
| Steven | 5000008 | tech@goodmail.com |
| Steven | 5000008 | feler@campus.uni.com |
| John | 5000005 | Smithley@goodmail.com.com |
| John | 5000005 | Smithley.j@gmail.com |
| George | 5000004 | georgestanko@hotmail.com |
| Ashley | 8000009 | Ashley.hill86@gmail.com |
| Amy | 5000003 | NULL |
+----------+---------+------------------------------+
然而,当我尝试加入电子邮件和电话时,我得到了这样一个信息:
+---------+----------+
| ID | Name |
+---------+----------+
| 5000003 | Amy |
| 5000004 | George |
| 5000005 | John |
| 5000008 | Steven |
| 8000009 | Ashley |
+---------+----------+
+---------+-----------------+
| ID | Number |
+---------+-----------------+
| 5000005 | 5551234 |
| 5000005 | 5154324 |
| 5000008 | 2487312 |
| 8000009 | 7134584 |
| 5000008 | 8451384 |
+---------+-----------------+
+---------+------------------------------+
| ID | Email |
+---------+------------------------------+
| 5000005 | Smithley@goodmail.com.com |
| 5000005 | Smithley.j@gmail.com |
| 5000008 | Smithley@gmail.com |
| 5000008 | tech@goodmail.com |
| 5000008 | feler@campus.uni.com |
| 8000009 | Ashley.hill86@gmail.com |
| 5000004 | georgestanko@hotmail.com |
+---------+------------------------------+
SELECT People.Name, People.ID, Phones.Number, Emails.Email
FROM People
LEFT OUTER JOIN Phones ON People.ID = Phones.ID
LEFT OUTER JOIN Emails ON People.ID = Emails.ID
ORDER BY Name, ID, Number, Email;
+----------+---------+-----------------+------------------------------+
| Name | ID | Number | Email |
+----------+---------+-----------------+------------------------------+
| Steven | 5000008 | 8451384 | feler@campus.uni.com |
| Steven | 5000008 | 8451384 | Smithley@gmail.com |
| Steven | 5000008 | 8451384 | tech@goodmail.com |
| Steven | 5000008 | 24887312 | feler@campus.uni.com |
| Steven | 5000008 | 24887312 | Smithley@gmail.com |
| Steven | 5000008 | 24887312 | tech@goodmail.com |
| John | 5000005 | 5551234 | Smithley@goodmail.com |
| John | 5000005 | 5551234 | Smithley.j@gmail.com |
| John | 5000005 | 5154324 | Smithley@goodmail.com |
| John | 5000005 | 5154324 | Smithley.j@gmail.com |
| George | 5000004 | NULL | georgestanko@hotmail.com |
| Ashley | 8000009 | 7134584 | Ashley.hill86@gmail.com |
| Amy | 5000003 | NULL | NULL |
+----------+---------+-----------------+------------------------------+
发生的情况是-如果一个人有两个号码,他的所有电子邮件都会显示两次(它们无法排序!这意味着@last无法删除它们)
我想要的是:
总之,玩@last,我想最终得到这样的东西,但是如果我不按正确的方式排列订单列,@last将不起作用-这似乎是一个大问题..在电子邮件列中排序。因为从上面的例子可以看出:
史蒂文有2个电话号码和3封电子邮件。带有数字的连接电子邮件发生在每封电子邮件中-因此无法排序的重复值(排序方式对它们不起作用)
现在有人告诉我,最好将电子邮件和数字放在分开的表格中,因为一个人可以有很多电子邮件。那么,如果这是一件很常见的事情,有什么不简单的解决方案呢
我也很乐意使用PHP解决方案
我现在知道该怎么做了,这让我很满意,但并没有那么漂亮。
如果我与GROUP_CONTACT这样做,结果会令人满意,但它看起来并不漂亮:我不能在它旁边放一个“Email type=work”
SELECT People.Ime,
GROUP_CONCAT(DISTINCT Phones.Number),
GROUP_CONCAT(DISTINCT Emails.Email)
FROM People
LEFT OUTER JOIN Phones ON People.ID=Phones.ID
LEFT OUTER JOIN Emails ON People.ID=Emails.ID
GROUP BY Name;
+----------+----------------------------------------------+---------------------------------------------------------------------+
| Name | GROUP_CONCAT(DISTINCT Phones.Number) | GROUP_CONCAT(DISTINCT Emails.Email) |
+----------+----------------------------------------------+---------------------------------------------------------------------+
| Steven | 8451384,24887312 | Smithley@gmail.com,tech@goodmail.com,feler@campus.uni.com |
| John | 5551234,5154324 | Smithley@goodmail.com,Smithley.j@gmail.com |
| George | NULL | georgestanko@hotmail.com |
| Ashley | 7134584 | Ashley.hill86@gmail.com |
| Amy | NULL | NULL |
+----------+----------------------------------------------+---------------------------------------------------------------------+
你想要的其实根本不是你想要的,如果这有道理的话。。。实际上,您无法通过编程方式对数据库输出执行任何操作,您需要对其执行一些操作(除非您只是直接在数据库上运行查询) 既然你说“我也很乐意使用PHP解决方案”。。。您真正想要的是类似于PHP“用户”对象的东西,类似于(当然这都是假设的):
然后,您的数据库抽象对象只需要执行一些非常简单的查询来读取用户、用户电子邮件和电话号码表,并将结果作为数组返回,然后您可以将这些数组直接放入PHP对象中。例如:
<?php
/**
* this implements a database connection object as a private class member
*/
class DBUser {
private $_conn;
/* constructor other functionality */
/**
* method to pass an SQL query to the database and return an array of results
*/
public function readTelNos($iUserId) {
return $this->_conn->read("SELECT `number` from `tel` WHERE `user_id` = " . (int) $iUserId);
}
}
?>
这会将您的问题分解为更小、更易于处理的问题,并将它们封装在漂亮的PHP对象中,然后您可以实际使用这些对象
您的用户对象将有一个列表,如果电话号码和电子邮件可以很容易地通过
$oUser->getEmails()等方式检索如果它们作为关联数组存储在对象中,您甚至可以通过“label”$oUser->getEmail('work')检索它们代码>如果我理解正确,您还需要将其他字段与电子邮件关联(例如:键入)
使用group_concat,您可以将电子邮件类型添加到结果中,在我的示例中是“;”将邮件与类型分开“,”将结果分开
SELECT u.name,
GROUP_CONCAT( distinct p.phone),
GROUP_CONCAT( distinct 'mail=',e.mail,';type=' ,type)
FROM people u
LEFT OUTER JOIN phone p ON u.id=p.id
LEFT OUTER JOIN mail e ON u.id=e.id
GROUP BY u.id
首先创建临时表名temp_tb,然后插入记录。然后使用Row_Number()进行分区,并多次删除列出的所有记录。就像被打了一样
Insert into temp_tb SELECT People.Name, People.ID, Phones.Number, Emails.Email
FROM People
LEFT OUTER JOIN Phones ON People.ID = Phones.ID
LEFT OUTER JOIN Emails ON People.ID = Emails.ID
ORDER BY Name, ID, Number, Email;
SELECT * from temp_tb
With A as
(
select People.Name, People.ID, Phones.Number, Emails.Email ROW_NUMBER()
OVER (Partition by ID ORDER BY Fee_temp.Name) As Number from temp_tb
)
DELETE FROM A WHERE Number>1
SELECT * FROM temp_tb
希望能对您有所帮助。您的表达有问题。不要在SQL中解决这个问题。这不是它的目的。+1用于详细说明和显示您面临的问题所需的基本背景信息。:)如果MySQL有一种简单的方法来实现带有窗口功能的行号,这将是非常容易的。@bluefeet:使用一个变量从aTable中选择@rownum:=rownum+1,(选择@rownum:=0)r
@juergend right,但MySQL在使用Thanke you时确实存在问题。我在学习php之前先学习数据库。(我知道C语言编程,所以我很擅长让某些东西工作,但还不知道如何让它看起来漂亮)。不客气,但如果这解决了你的问题,请记住标记我的答案为正确;)