努力弄清楚要使用哪些功能来获取我需要的功能-以升序列出所有公司及其所有用户。
到目前为止,我已经创建了两个表:“ companies”和“ users”,并使用外键将它们连接起来,如下所示:
我尝试执行JOIN查询以使用在一定程度上都有效的两个表,尽管我不知道如何纠正它。以下是我一直造成的原因:
如您所见,“ Contoso”公司被列出两次,因为它在users表中有2个与之关联的用户。我正在执行的代码是:
$joinquery = "SELECT companies.id, companies.name, users.fname, users.lname FROM users RIGHT JOIN companies ON users.cid = companies.id ORDER BY name ASC";
$joinresult = $mysqli->query($joinquery);
if($joinresult->num_rows > 0) {
while($row = $joinresult->fetch_assoc()){
$company = $row['name'];
$fname = $row['fname'];
$lname = $row['lname'];
$name = $fname . " " . $lname;
echo "<div class='customer'>";
echo "<div class='name'>";
echo $company;
echo "</div>";
echo "<div class='contacts'>";
echo $name;
echo "</div>";
echo "</div>";
}
} else {
echo "No results";
}
div仅使其成为一个块元素并更改颜色。
如何让所有用户都在其相关公司内,而不是每个公司和用户都排成一行?我已经尝试过嵌套,但是离最终目标还很远,下面是代码:
// Nested Query Test
$nestquery1 = "SELECT companies.name, users.fname, users.lname FROM companies INNER JOIN users ON companies.id = users.cid ORDER BY companies.name ASC";
$nestresult1 = $mysqli->query($nestquery1);
$nestquery2 = "SELECT companies.id, users.fname, users.lname FROM users INNER JOIN companies ON users.cid = companies.id ORDER BY fname ASC";
$nestresult2 = $mysqli->query($nestquery2);
if($nestresult1->num_rows > 0) {
while($row = $nestresult1->fetch_assoc()){
$company = $row['name'];
echo "<div class='customer'>";
echo "<div class='name'>";
echo $company;
echo "</div>";
if($nestresult2->num_rows > 0) {
while($row = $nestresult2->fetch_assoc()){
$fname = $row['fname'];
$lname = $row['lname'];
$name = $fname . " " . $lname;
echo "<div class='contacts'>";
echo "<li>";
echo $name;
echo "</li>";
echo "</div>";
}
}
echo "</div>";
}
} else {
echo "No results";
}
非常感谢您的帮助!
答案 0 :(得分:2)
由于要按公司名称进行订购,因此您应该能够检查公司名称何时更改,以便知道何时创建新容器。
$currentCompany = "";
while($row = $joinresult->fetch_assoc()){
$company = $row['name'];
$fname = $row['fname'];
$lname = $row['lname'];
$name = $fname . " " . $lname;
if($currentCompany != $company) {
if($currentCompany != "")
echo "</div>";
$currentCompany = $company;
echo "<div class='customer'>";
echo "<div class='name'>";
echo $company;
echo "</div>";
}
echo "<div class='contacts'>";
echo $name;
echo "</div>";
}
答案 1 :(得分:1)
您有两个选择,(A)使用联接或(B)尝试使用两个查询。联接将要求您跟踪公司的更改,但是不会查询这两个查询。两种选择都有优点和缺点:
A)这样的联接速度很快,但是您将返回每条记录的公司详细信息,从而在与数据库的通信中产生额外的流量负载。如果数据库服务器位于单独的服务器上,或者您要处理的是巨大的数据集,那么这可能是一个问题。请记住,即使多余的数据看起来很小,也可以将其乘以预期的网站并发访问者数量,这可能会使数据库链接饱和。
@ abney317提供的示例是准确的,但是与其比较公司名称,不如比较cid
,因为它不仅性能更高,而且更可靠。
B)这是我会选择的方法,虽然实现起来会涉及更多点,并且需要两个查询而不是一个查询,但它是将来可扩展性和可维护性更高的选项。还将使您的代码更易于遵循和调试。
示例:
// Nested Query Test
$rsCompanies = $mysqli->query("SELECT cid, name FROM companies ORDER BY name");
while($company = $rsCompanies->fetch_assoc())
{
echo "<div class='customer'>";
echo "<div class='name'>" . htmlspecialchars($company['name']) . "</div>";
echo "<div class='contacts'>";
echo "<ul>";
$rsUsers = $mysqli->query("SELECT fname, lname FROM users WHERE cid = " . $company['id']);
while($user = $rsUsers->fetch_assoc())
{
$name = htmlspecialchars($user['fname'] . " " . $user['lname']);
echo "<li>$name</li>";
}
echo "</ul>";
echo "</div>";
echo "</div>";
}
更多注意事项:
从不包含任何HTML的数据库输出文本时,始终使用htmlspecialchars
,否则将使您容易受到XSS攻击媒介的攻击。</ p>
我没有SQL转义公司ID,因为根据您的数据库架构,它是整数,并且由于最终用户未提供它,因此可以安全地直接使用它,从而避免了任何额外的处理开销。 p>
答案 2 :(得分:-1)
如果只需要显示几个字段,则尝试在一个查询中获取数据: sql fiddle
SELECT c.name company_name,
group_concat(u.name) employees_name
FROM companies c JOIN users u on c.id = u.cid
group by c.name;