MySQL Outer Join 3 Tables - mysql

I have 3 sql tables and I want to make 1 table in html
The tables are:
Norm (norm_id, name, description, cluster_cluster_id, orden_orden_id)
Cluster (cluster_id, cluster_name)
Orden (orden_id, orden_name)
The table must contain:
norm_id - norm_name - norm - description - cluster_name - orden_name
I think i need to do this with a left outer join?
And how to show it in a table?
Right now i have
while($row = mysqli_fetch_array($result)){
echo "<tr>";
echo "<td>" . $row['norm_id'] . "</td>";
echo "<td>" . $row['norm_name'] . "</td>";
echo "<td>" . $row['description'] . "</td>";
echo "<td>" . $row['cluster_name'] . "</td>";
echo "<td>" . $row['orden_name'] . "</td>";
echo "</tr>";
}

You can make left outer join like, SELECT column-names
FROM table-name1 LEFT JOIN table-name2
ON column-name1 = column-name2
WHERE condition

Related

SQL - select both "child" and "parent" rows in a single query

I have a database filled with a lot of "empty" records and I want to get rid of those orphaned records.
The database is structured like this;
A child row that contains the real entry (meta_value)
A parent row that is "linked" to its child (by it's meta_key)
| meta_id post_id meta_key meta_value |
| |
| 011 301 ACF__P_01_01 Foo |
| 012 309 _ACF__P_01_01 field_5874d5 |
| 013 321 ACF__P_01_02 |
| 014 316 _ACF__P_01_02 field_54290a |
| 015 119 ACF__P_01_03 Bar |
| 016 101 _ACF__P_01_03 field_a04a88 |
| 017 119 ACF__P_01_03 |
| 018 101 _ACF__P_01_03 field_a04a88 |
| 019 149 ACF__P_01_03 |
| 020 111 _ACF__P_01_03 field_a04a88 |
| 021 169 ACF__P_01_03 Foo Bar |
| 022 171 _ACF__P_01_03 field_a04a88 |
It's easy to select all the (empty) "child" rows, with a query like this;
SELECT
*
FROM
wp_postmeta
WHERE
wp_postmeta.meta_key LIKE '%ACF__%'
AND
wp_postmeta.meta_value LIKE ''
But this query only fetches the (empty) "child" rows, not their "parent" row.
There are two logical conditions that bind the parent to the child;
The first row is always the child, immediately followed by its parent.
The parent row has the same "meta_key" value as it's child, but pre-fixed by an underscore.
Is there any way to create a SQL query that selects the empty child records (like I did above) and it's parent as well?
I prefer a single query to fetch them both - but when that's not possible, I could run two queries as well (first one to fetch the parent, second one to get the empty children, I guess).
I use Navicat for my database management, so it must be plain SQL - no PHP.
The query should spit out the results like this;
| meta_id post_id meta_key meta_value |
| |
| 013 321 ACF__P_01_02 |
| 014 316 _ACF__P_01_02 field_54290a |
| 017 119 ACF__P_01_03 |
| 018 101 _ACF__P_01_03 field_a04a88 |
| 019 149 ACF__P_01_03 |
| 020 111 _ACF__P_01_03 field_a04a88 |
So both the empty-childs (no value in the "meta_value") and it's parent (both have the same "meta_key", where the parent has an underscore.
With a self-join
Select *
from wp_postmeta c
join wp_postmeta p
on p.meta_key = '_' + c.meta_key
The above will only fetch "pairs" of parent-child records. If it's possible to have parents without children (I assume it's not possible to have children without parents), and you want all the parents, including the childless ones, use an outer join
Select *
from wp_postmeta p
left join wp_postmeta c
on '_' + c.meta_key = p.meta_key
In relational databases, there is no such concept as "after" or "before" unless you define it yourself and add data into the tables that implements that concept (like a datetimestamp, or sequentially increasing numeric key, or whatever. Without such artifacts, records in a relational database table do not have any implicit order.
Using PHP I was able to solve it. I iterate over the first result from a query (that fetches all the empty children) and fetch every row AFTER that child, inside the loop.
But that's PHP - I wanted pure SQL :)
<?php
$connection = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
if ($connection -> connect_errno > 0) {
die ("Unable to connect to database [" . $connection->connect_error . "]");
}
$query_1 = "SELECT * FROM `wp_postmeta` WHERE `meta_key` LIKE '%ACF%__' AND `meta_value` LIKE ''";
if (!$result_1 = $connection -> query($query_1)) {
die ("There was an error running query[" . $connection -> error . "]");
}
if ($result_1) {
$i = 0;
echo "<h2>ACF - empty fields</h2>";
echo "<table border=1 cellpadding=4 cellspacing=0 width=800>";
echo "<tr style='background:#eee;font-weight:bold;'><td>row</td><td>meta_id</td><td>post_id</td><td>meta_key</td><td>meta_value</td></tr>";
while ($row_1 = $result_1 -> fetch_assoc()) {
$i++;
echo "<tr>";
echo "<td width=100>" . sprintf('%03d', $i) . "</td>";
echo "<td width=100 style='background:#aaa;color:#fff;font-weight:bold;'>" . $row_1["meta_id"] . "</td>";
echo "<td width=100>" . $row_1["post_id"] . "</td>";
echo "<td width=100>" . $row_1["meta_key"] . "</td>";
echo "<td width=500>" . $row_1["meta_value"] . "</td>";
echo "</tr>";
$query_2 = "SELECT * FROM `wp_postmeta` WHERE `meta_id` = " . ($row_1["meta_id"] + 1);
if (!$result_2 = $connection -> query($query_2)) {
die ("There was an error running query[" . $connection -> error . "]");
}
while ($row_2 = $result_2 -> fetch_assoc()) {
$i++;
echo "<tr>";
echo "<td width=100>" . sprintf('%03d', $i) . "</td>";
echo "<td width=100 style='background:#aaa;color:#fff;font-weight:bold;'>" . $row_2["meta_id"] . "</td>";
echo "<td width=100>" . $row_2["post_id"] . "</td>";
echo "<td width=100>" . $row_2["meta_key"] . "</td>";
echo "<td width=500>" . $row_2["meta_value"] . "</td>";
echo "</tr>";
}
mysqli_free_result($result_2);
}
mysqli_free_result($result_1);
echo "</table>";
} else {
echo "No entries found.";
}
?>
- edit -
This PHP code is better, I guess... It uses only 2 queries and iterates over the first one...
It works perfectly, but still isn't pure SQL - I want to get rid of the PHP...
<?php
/* --------------------------------------------------- */
$connection = new mysqli(DB_HOST, DB_USER, DB_PASSWORD, DB_NAME);
if ($connection -> connect_errno > 0) {
die ("Unable to connect to database [" . $connection->connect_error . "]");
}
/* --------------------------------------------------- */
$query = "SELECT `meta_id` FROM `wp_postmeta` WHERE `meta_key` LIKE '%ACF%__' AND `meta_value` LIKE ''";
if (!$result = $connection -> query($query)) {
die ("There was an error running query[" . $connection -> error . "]");
}
if ($result) {
$array = array();
while ($row = $result -> fetch_assoc()) {
$array[] = $row["meta_id"];
$array[] = $row["meta_id"] + 1;
}
mysqli_free_result($result);
/* --------------------------------------------------- */
$query = "SELECT * FROM `wp_postmeta` WHERE `meta_id` IN (" . implode(",", array_map("intval", $array)) . ")";
if (!$result = $connection -> query($query)) {
die ("There was an error running query[" . $connection -> error . "]");
}
if ($result) {
$i = 0;
echo "<h2>ACF - empty fields</h2>";
echo "<table>";
echo "<tr><td>record</td><td>meta_id</td><td>post_id</td><td>meta_key</td><td>meta_value</td></tr>";
while ($row = $result -> fetch_assoc()) {
$i++;
echo "<tr>";
echo "<td>" . sprintf('%03d', $i) . "</td>";
echo "<td>" . $row["meta_id"] . "</td>";
echo "<td>" . $row["post_id"] . "</td>";
echo "<td>" . $row["meta_key"] . "</td>";
echo "<td>" . $row["meta_value"] . "</td>";
echo "</tr>";
}
mysqli_free_result($result);
echo "</table>";
if (isset($_GET["delete"])) {
echo "<span>all records deleted</span>";
} else {
echo "<a href='?delete'>delete empty records</a>";
}
}
/* --------------------------------------------------- */
} else {
echo "No entries found.";
}
?>

2 or 3 Checkboxes in MySQL query

I created the following SQL Query, which works fine. However, I want to add 2 other checkbox $Post's from another label. Now I'm a little bit without any idea how I can add it. Do I have to add an "AND" between the tbs queries?
Here is the code
include "db_connect.inc.php";
$sql = "SELECT * FROM profiles";
$sql .= " WHERE profilename = '". $_POST["profilename"] ."' ";
$sql .= " AND ort = '". $_POST["ort"] ."' ";
$sql .= "AND jahren = '" . $_POST["alter"] . "' ";
$tbs = array();
foreach( array( 'tb1', 'tb2', 'tb3' ) as $tb_key )
{
if ( empty( $_POST[$tb_key] ) ) continue;
$tbs[] = "`grosse` LIKE '" . $_POST[$tb_key] . "'";
}
if ( !empty( $tbs ) )
{
$sql .= ' AND ( ' . implode( ' OR ', $tbs ) . ' )';
}
$tbs = array();
foreach( array( 'tb4', 'tb5', 'tb6', 'tb7' ) as $tb_key )
{
if ( empty( $_POST[$tb_key] ) ) continue;
$tbs[] = "`haare` LIKE '" . $_POST[$tb_key] . "'";
}
if ( !empty( $tbs ) )
{
$sql .= ' AND ( ' . implode( ' OR ', $tbs ) . ' )';
}
$res = mysqli_query($con, $sql);
$num = mysqli_num_rows($res);
if ($num==0) echo "Kein Profil gefunden";
echo "<table border='1'>";
echo "<tr><td>Profile</td><td>Alter</td>";
echo "<td>Ort</td><td>Brustgrösse</td>";
echo "<td>Haarfarbe</td></tr>";
while ($dsatz = mysqli_fetch_assoc($res))
{
echo "<tr>";
echo "<td>" . $dsatz["profilename"] . "</td>";
echo "<td>" .$dsatz["jahren"] . "</td>";
echo "<td>" .$dsatz["ort"] . "</td>";
echo "<td>" .$dsatz["grosse"] . "</td>";
echo "<td>" .$dsatz["haare"] . "</td>";
echo "</tr>";
}
echo "</table>";
mysqli_close($con);
i could it resolve it. I had a wrong entry in the DB. The query works fine!

SELECT statement - ignore blank columns - joined tables

I'm joining 5 tables in vTiger in order to get all the info I need. However, there is an option that certain columns will be empty. In that case, my SELECT statement fails and I can't retrieve the rest of the results. How do I bypass this by adding a "Doesn't exist" default value if the column is blank?
$results = mysql_query("SELECT
vtiger_potentialscf.potentialid,
vtiger_potential.potentialname,
vtiger_contactdetails.accountid,
vtiger_contactdetails.salutation,
vtiger_contactdetails.firstname,
vtiger_contactdetails.lastname,
vtiger_account.accountname,
vtiger_crmentity.smownerid,
vtiger_crmentity.crmid,
vtiger_crmentity.label,
vtiger_users.id,
vtiger_users.email1
FROM vtiger_potential
INNER JOIN vtiger_potentialscf ON vtiger_potentialscf.potentialid = vtiger_potential.potentialid
INNER JOIN vtiger_crmentity ON vtiger_potential.potentialid = vtiger_crmentity.crmid
INNER JOIN vtiger_users ON vtiger_crmentity.smownerid = vtiger_users.id
INNER JOIN vtiger_contactdetails ON vtiger_potential.related_to = vtiger_contactdetails.accountid
INNER JOIN vtiger_account ON vtiger_account.accountid = vtiger_potential.related_to
WHERE `cf_919` = DATE(NOW())");
while ($row = mysql_fetch_assoc($results)) {
echo $row['email1'] . "<br />";
echo $row['smownerid'] . "<br />";
echo $row['potentialname'] . "<br />";
echo $row['accountid'] . "<br />";
echo $row['salutation'] . "<br />";
echo $row['firstname'] . "<br />";
echo $row['lastname'] . "<br />";
echo $row['accountname'] . "<br />";
In this case, I can have the vtiger_contactdetails empty. Any suggestion on how to get the rest of the content and just echo that these aren't available?
You could use left join.
Have a look http://www.w3schools.com/sql/sql_join_left.asp
Thanks Abhik Chakraborty for a much better explanation in the comments.

Changing date format from database

I am trying to change the date format before it is displayed with SQL query however the date format is being completely ignored.
my code is
$query = "SELECT * , DATE_FORMAT(formatted, '%d/%m/%Y') from movies;";
then further down this is my table
echo "<table>"
echo "<table border='2'>"
echo "<tr>
<th>id</th>
<th>title</th>
<th>date</th>
</tr>";
while($row = mysql_fetch_array($query))
{
echo "<tr>";
echo "<td>" . $row['id'] . "</td>";
echo "<td>" . $row['title'] . "</td>";
echo "<td>" . $row['formatted'] . "</td>";
echo "</tr>";
}
echo "</table>";
?>
this query is working, however the date format is being ignored and just displaying the date in yyyy-mm-dd I want it in DD-MM-YY.
thanks
Use an alias to name your calculated column
SELECT * , DATE_FORMAT(datetime, '%d/%m/%Y') AS formatted_date
from movies
Use a different name than the existing column to differ between the two. Then use
echo "<td>" . $row['formatted_date'] . "</td>";
to get the formatted one.
You need to mention the alias for the formatted datetime column other wise formatted value will not be called in your code
SELECT * ,
DATE_FORMAT(`datetime`, '%d/%m/%Y') `datetime`
from movies

combine two pdo queries showing all results from the 2nd.

I had one table listing events and attendies. To try Database normalization i split this into two tables.
I have made a database listing all the planned games for a team.
Table 1
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+name + organiser + date + location + cost + notes + id+
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
i then have a second database that has everyone how has marked they will be comming
Table 2
++++++++++++++++++++++++++
+id + event + player +
++++++++++++++++++++++++++
The id is unique to each, The id from table 1 is used as the event in table 2.
i have a simple PDO query that pulls the data from table 1 into a HTMl table
if($db->connect_error) {
die("Connection error: ".$db->connect_error);
}
$sql = $db->query('SELECT * FROM event ORDER BY `date` ASC'
) or die($db->error);
echo"";
while($row = mysqli_fetch_assoc($sql))
{
$a = $row['attendees'];//will look up attendies to tick a check box if already aknowledged
$b = htmlentities($_SESSION['user']['username'], ENT_QUOTES, 'UTF-8');
if (strpos($a,$b) !== false) {
$c = "checked='checked'";
}else{
$c = "";
}
$r=$row['id'];
echo "<div id='results'>";
echo "<CENTER>";
echo "<table BORDER=6 class='fixed'>";
echo "<TR> ";
echo "<TD COLSPAN=3 ALIGN=CENTER><form action='going.php' method='post' name='form".$r."'>Event ".$row['name']." i'm going
<input type='checkbox' name='going'".$c." onclick='document.form".$r.".submit ();'>
<input type='text' name='Organise' value='".$r."'>
<input type='text' name='name' value='".$b."'>
</form></TD>";
echo "</TR> ";
echo "<TR>";
echo "<td>";
echo "<B><u><font color='#0080FF'>Title </font></b></u>".$row['name']."<br></font>";
echo "<B><u><font color='#0080FF'>Orginiser </font></b></u>".$row['organiser']."<br></font>";
echo "<B><u><font color='#0080FF'>When </font></b></u>".date("D j-M-Y GA",$row['dt'])."<br></font>";
echo "<B><u><font color='#0080FF'>Location </font></b></u>".$row['location']."<br></font>";
echo "<B><u><font color='#0080FF'>Cost </font></b></u>£".$row['cost']."<br></font></TD>";
echo "<TD ROWSPAN=3 valign='top'><B><u><font color='#0080FF'>Attendies </font></b></u>".$row['attendees']."<br></font></TD>";//will change to table 2
echo "<TD ROWSPAN=3 valign='top'><B><u><font color='#0080FF'>notes </font></b></u>".$row['notes']."<br></font></TD>";
echo "</tr>";
echo "</table>";
echo "</CENTER>";
echo "</div>";
}
i have tried and joind these using
$sql = $db->query('SELECT t1.*, t2.event as t2event, t2.player as player
FROM `event` as t1
LEFT JOIN `going` as t2 on t1.id = t2.event
ORDER BY t1.`dt` ASC'
but all i got was a HTML table per event and per player. I'm sure its possible but can't work it out, can i create a html table from quering table 1 and add to attendies all those going from table 2 not just one or creating a result each one. ?