Changing a field from a table depending on a mysql query - php

The prototype software I am creating uses the MVC framework.
I am trying to change the allowed field in the entrylog table to either "Y" (Yes) or "N" (no) depending on whether a card associated with a driver is authorised or not.
The four tables involved are card, driver, state and the entrylog table. Also there is a card_driver table which associates a card with a driver.
CREATE TABLE IF NOT EXISTS `card` (
`id` int(11) NOT NULL auto_increment,
`startdate` date NOT NULL,
`enddate` date NOT NULL,
`state_id` int(11) NOT NULL,
`referred_as` varchar(40) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS `driver` (
`id` int(11) NOT NULL auto_increment,
`title` varchar(40) default NULL,
`supplier_id` int(11) NOT NULL,
`referred_as` varchar(40) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS `card_driver` (
`card_id` int(11) NOT NULL,
`driver_id` int(11) NOT NULL
);
CREATE TABLE IF NOT EXISTS `state` (
`id` int(11) NOT NULL auto_increment,
`referred_as` varchar(40) NOT NULL,
PRIMARY KEY (`id`)
);
CREATE TABLE IF NOT EXISTS `entrylog` (
`id` int(11) NOT NULL auto_increment,
`vehicle_id` int(11) NOT NULL,
`driver_id` int(11) NOT NULL,
`venue_id` int(11) NOT NULL,
`supplier_id` int(11) NOT NULL,
`deliverydate` date NOT NULL,
`allowed` binary(1) NOT NULL default 'N',
PRIMARY KEY (`id`)
);
In the driver table I currently have code which checks the authorisation of a selected drivers associated card. I would like to apply this similiar code to the entry log, so that when using a form to enter a delivery it determines the 'allowed' field automatically. The code to check the drivers authorisation in the driver table is as follows:
if ($name == driver) {
?>
<? include('common.php') ?>
<?php
if(isset($_POST['check']))
{
$conn = mysql_connect($server, $db_user, $db_pass);
if(! $conn )
{
die('Could not connect: ' . mysql_error());
}
$id = $_POST['id'];
$sql ="SELECT *
FROM driver AS d
INNER
JOIN card_driver AS cd
ON cd.driver_id = d.id
INNER
JOIN card AS c
ON c.id = cd.card_id
WHERE d.ID = $id";
mysql_select_db('damp');
$result = mysql_query( $sql, $conn );
$row = mysql_fetch_assoc($result);
switch($row['state_id'])
{
case "1":
echo "<strong><font color=\"green\">Authorisation Granted!</font></strong>";
break;
case "2":
echo "<strong><font color=\"red\">Your card has expired and authorisation is denied</font></strong>";
break;
case "3":
echo "<strong><font color=\"red\">Your card has been cancelled and authorisation is denied</font></strong>";
break;
default:
echo "<strong><font color=\"red\">The Card ID does not exist</font></strong>";
}
Thank you for any help or advise you can give me.
EDIT : Code from controller_create.php
if ($class_obj == "entrylog")
{
$id = $_POST['id'];
$driverid = MyActiveRecord::FindById('driver',$this_obj->driver_id);
$query = mysql_query("SUPDATE entrylog el
INNER JOIN driver AS d ON d.driver_id = el.driver_id
INNER JOIN card_driver AS cd ON cd.driver_id = d.id
INNER JOIN card AS c ON c.id = cd.card_id
SET el.allowed = CASE WHEN c.state_id = 1
THEN 'Y'
ELSE 'N'
END
WHERE el.ID = $entryLogId");
mysql_select_db('damp');
}

Not entirely clear on what you're asking but the following may help:
UPDATE entrylog el
INNER JOIN driver AS d ON d.id = el.driver_id
INNER JOIN card_driver AS cd ON cd.driver_id = d.id
INNER JOIN card AS c ON c.id = cd.card_id
SET el.allowed = CASE WHEN c.state_id = 1
THEN 'Y'
ELSE 'N'
END
WHERE el.ID = $entryLogId
From your most recent comment it sounds like this value should be calculated as part of your INSERT though, rather than an UPDATE later.

Related

How to show reviews per restaurant in php with mysql?

I am trying to show the amount of reviews for each restaurant.
I made 2 tables containing my data.
CREATE TABLE `restaurants` (
`id` int(4) NOT NULL AUTO_INCREMENT,
`name` varchar(200) NOT NULL,
`city` varchar(200) NOT NULL,
`country` varchar(200) NOT NULL,
`score` int(1) NOT NULL DEFAULT '0',
`reviews` int(1) NOT NULL DEFAULT '0',
`slug` varchar(200) NOT NULL DEFAULT 'slug-test',
`approved` int(1) NOT NULL DEFAULT '0',
`description` text NOT NULL,
`review` int(11) DEFAULT '0',
`created_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_date` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`img_url` varchar(255) NOT NULL,
`category` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=65 DEFAULT CHARSET=latin1
CREATE TABLE `reviews` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`restaurant_id` int(11) NOT NULL,
`review_text` text NOT NULL,
`score` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `restaurant_id` (`restaurant_id`),
CONSTRAINT `reviews_ibfk_1` FOREIGN KEY (`restaurant_id`) REFERENCES `restaurants` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1
I am already showing my restaurants in a list.
$query = "SELECT * FROM restaurants WHERE approved = 1 ORDER BY created_date DESC";
$result = $mysqli->query($query);
while($row = $result->fetch_array()) {
**HTML WITH MY VARIABLES**
}
This is how u currently show my reviews (hardcoded result in my restaurants table.
if ($reviews <= "0") {
echo "<a href='#' title='Write reviews'><p class='purple-def-color fz-12 mb-0'>write a review</p></a>";
} else if ($reviews > "1") {
echo "<p class='purple-def-color mb-0'>". $row['reviews'] ." reviews</p>";
} else {
echo "<p class='purple-def-color mb-0'>" . $row['reviews'] . " review</p>";
}
I tried to use a JOIN query but was not successful to show the amount of reviews in any way.
Based on your table structure, you can get a review count for each restaurant by joining the reviews table, selecting the COUNT of reviews, and grouping by restaurant ID.
Grouping by restaurant allows you to get an aggregate (e.g. count) of the joined review records for each restaurant.
SELECT
rs.*,
COUNT(rv.`id`) as `reviewCount`
FROM `restaurants` rs
LEFT JOIN `reviews` rv
ON (rv.`restaurant_id` = rs.`id`)
WHERE rs.`approved` = 1
GROUP BY rs.`id`
ORDER BY rs.`created_date` DESC;
Then, when you fetch the rows in PHP, you can reference each row's review count:
echo $row['reviewCount'];
To further demonstrate aggregate functions, here's an example of how to select the average, minimum, and maximum review score for each restaurant:
SELECT
rs.*,
COUNT(rv.`id`) as `reviewCount`,
AVG(rv.`score`) as `reviewAverageScore`,
MIN(rv.`score`) as `reviewMinScore`,
MAX(rv.`score`) as `reviewMaxScore`
FROM `restaurants` rs
LEFT JOIN `reviews` rv
ON (rv.`restaurant_id` = rs.`id`)
WHERE rs.`approved` = 1
GROUP BY rs.`id`
ORDER BY rs.`created_date` DESC;
Try a left join:
$query = 'SELECT * FROM restaurants LEFT JOIN reviews on reviews.restaurant_id = restaurants.id'
A left join returns all records from the left table (restaurants), and the matched records from the right table (reviews)

How to write nested query MySQL PHP

I'm developing a page to edit board meetings and I want to display all board members who did not attend specific meeting as a checkox located below who attend as an edit in case of user want to add more so I did this:
My code:
$q = "SELECT * FROM `boardteam`";
$r = mysql_query($q);
while ($dbfield = mysql_fetch_assoc($r))
{
$member_id =$dbfield['nationalID'];
$query = "SELECT `attendance` FROM `meetingattendance` WHERE `meetingID` = '$mid' AND `attendance`!= '$member_id'";
$res = mysql_query($query);
if ($res)
{
$tname ="";
switch ($dbfield['titleName'])
{
case "Dr":
$tname .= "د.";
break;
case "Ms":
$tname .= "السيدة.";
break;
case "Mr":
$tname .= "السيد.";
break;
}
$At .= "<input type='checkbox' name='moreAttendence[]' dir='rtl' value=".$dbfield['nationalID']."><div class='styled-checkbox'>".$tname." ".$dbfield['fName']." ".$dbfield['sName']." ".$dbfield['lName']."</div><br>";
}
}
DB:
CREATE TABLE `boardteam` (
`nationalID` int(10) NOT NULL,
`titleName` char(2) NOT NULL,
`fName` char(20) NOT NULL,
`sName` char(20) NOT NULL,
`lName` char(20) NOT NULL,
`gender` char(1) NOT NULL,
`birthDate` date DEFAULT NULL,
`materialStatus` char(15) DEFAULT NULL,
`jobTitle` varchar(100) NOT NULL,
`jobLocation` varchar(20) DEFAULT NULL,
`employer` varchar(100) DEFAULT NULL,
`email` varchar(100) NOT NULL,
`photo` varchar(255) DEFAULT NULL,
`academicGrade` char(15) DEFAULT NULL,
`employmentStartDate` date NOT NULL,
`employmentEndDate` date NOT NULL,
`employmentType` char(20) DEFAULT NULL,
`employmentStatus` char(15) DEFAULT NULL,
`jobStartDate` date DEFAULT NULL,
`jobNumber` int(10) DEFAULT NULL,
`cv` varchar(255) DEFAULT NULL,
PRIMARY KEY (`nationalID`)
)
CREATE TABLE `meetingattendance` (
`meetingID` int(11) NOT NULL,
`attendance` int(10) DEFAULT NULL,
`absence` int(10) DEFAULT NULL,
`reason` varchar(255) DEFAULT NULL,
`additionalAttendance` varchar(255) DEFAULT NULL,
KEY `absence` (`absence`),
KEY `meeingID` (`meetingID`),
KEY `attendance` (`attendance`),
CONSTRAINT `meetingattendane_ibfk_1` FOREIGN KEY (`meetingID`) REFERENCES `boardmeetings` (`meetingID`),
CONSTRAINT `meetingattendane_ibfk_2` FOREIGN KEY (`attendance`) REFERENCES `boardteam` (`nationalID`),
CONSTRAINT `meetingattendane_ibfk_3` FOREIGN KEY (`absence`) REFERENCES `boardteam` (`nationalID`)
)
With my code I got all board members including who attend, How to fix that ??
You need to use a LEFT JOIN in order to find people in the boardTeam who were not in a specific meeting. eg:
SELECT b.*, m.attendance
FROM boardTeam b
LEFT JOIN meetingattendance m
ON b.nationalID = m.attendance AND m.meetingID = $mid
WHERE m.meetingID IS NULL
If you want to get ALL board members, and then determine within PHP if they attended the meeting or not, simply remove the m.attendance IS NULL clause, as such:
SELECT b.*, m.attendance as attendance
FROM boardTeam b
LEFT JOIN meetingattendance m
ON b.nationalID = m.attendance AND m.meetingID = $mid
and now when you loop through the response rows in php, you can test as such (assuming you fetch your rows one by one into a $row variable):
if($row['attendance'] != null)
{
// attended meeting
}
else
{
// did not attend meeting
}
Also, as mentioned in the comments, use mysqli, or pdo instead of pure mysql_ functions
Example fiddle here: http://sqlfiddle.com/#!9/ba7d4/6

PHP something wrong with while loop

Okay so now its display results like 3 times in a row
$user_apps = mysql_query("SELECT a.name,a.download_url FROM user_apps as ua LEFT JOIN
apps as a ON (ua.app_id=a.app_id)
WHERE ua.user_id='$user_id'") or die(mysql_error());
while($raw = mysql_fetch_array($user_apps)){
$name = $raw['name'];
$url = $raw['download_url'];
echo $name;
echo "<br />";
echo $url;
}
Database Table Structure(since I am new to the site and did not know how to display the table structure I just exported the sql)
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=9 ;
CREATE TABLE IF NOT EXISTS `user_apps` (
`user_id` int(11) NOT NULL,
`app_id` int(11) NOT NULL,
KEY `user_id` (`user_id`,`app_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE IF NOT EXISTS `apps` (
`app_id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`description` text NOT NULL,
`icon` varchar(255) NOT NULL,
`download_url` varchar(255) NOT NULL,
`default` int(20) NOT NULL DEFAULT '0',
PRIMARY KEY (`app_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=10 ;
I'v tried different Join types but that does not seem to work.
Used the join query for get the result check bellow example query
$user_apps = mysql_query("SELECT DISTINCT a.name,a.download_url FROM user_apps as ua LEFT JOIN apps as a ON (ua.app_id=a.app_id) WHERE ua.user_id='$user_id'") or die(mysql_error());
while($raw = mysql_fetch_array($user_apps)){
$name = $raw['name'];
$url = $raw['download_url'];
echo $name;
echo $url;
}
change the join type as per your requirement. the above query for only example
INNER JOIN: Returns all rows when there is at least one match in BOTH
tables
LEFT JOIN: Return all rows from the left table, and the matched rows
from the right table
RIGHT JOIN: Return all rows from the right table, and the matched
rows from the left table
FULL JOIN: Return all rows when there is a match in ONE of the tables
more about join click here
AND also check this http://blog.codinghorror.com/a-visual-explanation-of-sql-joins/
You have used single quotes in query at user_id='$user_id' .
Are you sure your user_id is char, varchar or text? Just print_r($user_apps) and check it has any records or not? If user_id is int,tinyin than remove single quote.

Joining streamitem_creator in streamdata to users table

I have two tables. One which holds the user status content and the other holding the users. How do I write the query of the users to obtain the user record for their given streamitem in streamdata? At current times, its only grabbing the user that is at the top of the user table.
$check = "SELECT streamitem_id, streamitem_timestamp, streamitem_content FROM streamdata WHERE streamitem_creator="$user1_id." AND streamitem_id=".$last." AND streamitem_type_id=1 ORDER BY streamitem_timestamp DESC";
$check1 = mysqli_query($mysqli,$check);
$resultArr = mysqli_fetch_array($check1);
$json['streamitem_id'] = $resultArr['streamitem_id'];
$json['streamitem_timestamp'] = Agotime($resultArr['streamitem_timestamp']);
$json['streamitem_content'] = $resultArr['streamitem_content'];
mysqli_free_result($check1);
$check = "SELECT * FROM users";
$check1 = mysqli_query($mysqli,$check);
$resultArr = mysqli_fetch_array($check1);
$json['username'] = $resultArr['username'];
$json['id'] = $resultArr['id'];
$json['first'] = $resultArr['first'];
$json['middle'] = $resultArr['middle'];
$json['last'] = $resultArr['last'];
mysqli_free_result($check1);
-- Table structure for table `streamdata`
--
CREATE TABLE IF NOT EXISTS `streamdata` (
`streamitem_id` int(11) NOT NULL auto_increment,
`streamitem_type_id` int(11) NOT NULL,
`streamitem_creator` int(11) NOT NULL,
`streamitem_target` int(11) NOT NULL,
`streamitem_timestamp` datetime NOT NULL,
`streamitem_content` varchar(5000) NOT NULL,
PRIMARY KEY (`str
eamitem_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1953 ;
-- Table structure for table `users`
--
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL auto_increment,
`first` varchar(64) NOT NULL,
`middle` varchar(64) NOT NULL,
`last` varchar(64) NOT NULL,
`username` varchar(64) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=150 ;
Query to get user details and stream details for a given stream item:
$check = "
SELECT * FROM users u
INNER JOIN streamdata s ON
(s.streamitem_creator = u.id AND s.streamitem_id = {$last})";
Please note that it is bad practice to insert raw variable values into your queries. Especially if they come from user input. Look into mysqli_real_escape_string or try using prepared statements.

SQl query to select relational data

I am trying to write the SQL that selects all products and available features.
My database is as follows:
CREATE TABLE IF NOT EXISTS `products` (
`product_id` int(11) NOT NULL AUTO_INCREMENT,
`product_name` varchar(255) NOT NULL,
`product_description` varchar(255) NOT NULL,
`product_weight` varchar(255) NOT NULL,
`product_price` decimal(11,2) NOT NULL,
`product_image` varchar(255) NOT NULL,
PRIMARY KEY (`product_id`)
);
CREATE TABLE IF NOT EXISTS `features` (
`feature_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`feature_uri` varchar(255) NOT NULL,
`feature_name` varchar(100) NOT NULL,
`feature_title` varchar(150) DEFAULT NULL,
`feature_body` text,
`feature_body_short` varchar(255) DEFAULT NULL,
`feature_image` varchar(255) DEFAULT NULL,
`parent_id` int(11) unsigned NOT NULL,
PRIMARY KEY (`feature_id`),
UNIQUE KEY `feature_uri_UNIQUE` (`feature_uri`),
KEY `parentFK` (`feature_id`),
FULLTEXT KEY `feature_name_FT` (`feature_name`),
FULLTEXT KEY `feature_body_FT` (`feature_body`)
);
CREATE TABLE IF NOT EXISTS `feature_products` (
`feature_product_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`feature_product_order` smallint(6) DEFAULT NULL,
`feature_product_standard` tinyint(1) NOT NULL,
`feature_id` int(11) unsigned NOT NULL,
`product_id` int(11) unsigned NOT NULL,
PRIMARY KEY (`feature_product_id`),
KEY `productFK` (`product_id`),
KEY `featureFK` (`feature_id`)
);
I would like to be able to do this in one loop e.g:
{foreach}
<tr>
<td>{name}</td>
<td>{weight}</td>
<td>{if product_id == 1}yes{/if}</td>
<td>{if product_id == 2}yes{/if}</td>
etc
<tr>
{/foreach}
I am using Zend, if this can be of use.
Trying to achieve this HTML:
UPDATE:
Non of the suggested answers are working, instead I managed to hack it to work like this:
SELECT
p.*,
(
SELECT
GROUP_CONCAT(f.feature_id SEPARATOR ', ')
FROM feature_products fp
LEFT JOIN features f ON f.features_id = fp.feature_id
WHERE fp.product_id = p.product_id
LIMIT 1
) as features
FROM product p
Although the problem with the above code is that it does not return 'feature_product_standard'
I'm assuming that you have MySQL, dunno about Zend, but this should get you started.
SELECT
p.product_name
, p.product_description
, p.product_weight
, p.product_price
, p.product_image
, GROUP_CONCAT(f.feature_id ORDER BY f.feature_id) as feature_ids
, GROUP_CONCAT(f.feature_name ORDER BY f.feature_id) as feature_names
FROM products p
LEFT JOIN feature_products fp ON (fp.product_id = p.product_id)
LEFT JOIN features f ON (f.feature_id = fp.feature_id)
GROUP BY p.product_id
Not very good code i know, but i hope it helps.
This is using Johan's SQL code.
I haven't tested this.
$connection = odbc_connect("Connection info here");
$query = "SELECT
p.product_name
, p.product_description
, p.product_weight
, p.product_price
, p.product_image
, GROUP_CONCAT(f.feature_id ORDER BY f.feature_id) as feature_ids
, GROUP_CONCAT(f.feature_name ORDER BY f.feature_id) as feature_names
FROM products p
LEFT JOIN feature_products fp ON (fp.product_id = p.product_id)
LEFT JOIN features f ON (f.feature_id = fp.feature_id)";
$result = odbc_exec($connection, $query);
while ($data[] = odbc_fetch_array($result));
odbc_close($connection);
if ($data[0]["product_name"]) {
echo "<table><tr>";
foreach (array_keys($data[0]) as $a) { $message .= "<th>".$a."</th>"; }
foreach ($data as $d) {
if ($d["product_name"]) {
if ($d) {
echo "</tr><tr>\n";
foreach ($d as $s) {
echo "<td>".$s."</td>";
}
}
}
}
}

Categories