Linking together multiple tables to grab information from each - sql

I am creating a page that displays info on equipment that has been scanned into and out of my office. The way I want it to display is
Equipment Name User(Headtech) Event used Returned(Y/N)
The problem is the SQL tables are everywhere and joining them all is proving to be difficult. There needs to be a chain going through three tables to get the Head tech name, this was not of my design and I can not change it.
What I currently have
$select = mysqli_query($con, "SELECT *
FROM equipment
JOIN pay
ON pay.eventid = equipment.eventid
JOIN personnel
ON personnel.workerid = (pay.eventid WHERE role = 'aht')
JOIN events
ON events.id = equipment.eventid
WHERE status='3'
ORDER By timeOut DESC");
while($row = mysqli_fetch_array($select)) {
$name = $row['name'];
$timeIn = $row['timeIn'];
$timeOut = $row['timeOut'];
$eventID = $row['eventid'];
echo "<div><div class='rowBoxS'>$name</div>";
$htName = $row['personnel.first'] . " " . $row['perosnnel.last'];
echo "<div class='rowBoxS'>$htName</div>";
$event = $row['eventName'];
echo "<div class='rowBoxS'>$event</div>";
if ($timeOut > 0){
echo "<div class='rowBoxS'>$</div></div>";
}
else{
echo "<div class='rowBoxS'>Failed to return</div></div>";
}
This is clearly not working as intended, and I'm very aware that that is probably not how joining works especially with the pay.eventid WHERE role = 'aht' bit. I want to know if there is a proper way to approach this. I tried looking it up, but most people probably have clean databases they are working with and couldn't possibly run into this problem.
Edit:
All the tables are on the same server. The problem is if I want to get someone's name you need to use the eventid row from equipment on the pay table find that id, then through the 'role' row find the user with AHT role and then take that persons workerid into the personnel table where you can finally find the persons name.

Related

Prestashop module SQL Query to get id_products from a specific feature value

I'm currently working with a module called "Leo Parts Filter" on prestashop, which sort id_products by make, model, year and device in a database "ps_leopartsfilter_product".
When i call a make, model, year a device that have an id_product in this table, prestashop show this id_product.
public static $definition = array(
'table' => 'leopartsfilter_product',
'primary' => 'id_product',
'multilang' => false,
$sql = 'SELECT * FROM `' . _DB_PREFIX_ . 'leopartsfilter_product` WHERE 1=1 ';
if ($id_product != null && (int) $id_product) {
$sql .= ' AND id_product =' . (int) id_product;
}
I would like to change the way id_product is called, instead of calling only this id_product according this way :
I would like to query all products where the feature_id = 212 and where the feature_value_lang = id_product.
I tried to adapt this query but i can't make it work correctly (no data showing)
SELECT id_product, fl.name, value, pf.id_feature
FROM '._DB_PREFIX_.'feature_product pf
LEFT JOIN '._DB_PREFIX_.'feature_lang fl ON (fl.id_feature =212 AND fl.id_lang = '.(int)$context->language->id.')
LEFT JOIN '._DB_PREFIX_.'feature_value_lang fvl ON (fvl.id_feature_value = pf.id_feature_value AND fvl.id_lang = '.(int)$context->language->id.')
LEFT JOIN '._DB_PREFIX_.'feature f ON (f.id_feature = pf.id_feature)
'.Shop::addSqlAssociation('feature', 'f').'
WHERE fvl.`value` = '['id_product']'
GROUP BY id_product
ORDER BY f.position ASC
';
I'm not good at SQL so don't blame me, i learned everything by my way and i try to build my own company website, this module is all i need to finish.
If someone want some money for help, i'm open to give rewards to make it work.
Thanks
Your second query has nothing to do with the Leo Parts Filter module, since it only queries native Prestashop feature tables and not those of the Leo module itself, so your request is not very clear.
If you need to rely on basic features, it must be clear to you that the relationship between id features / id feature values and id products is all in the ps_feature_product table, so if you want products that have id_feature_value = 212 you just need a simple
SELECT id_product FROM ps_feature_product WHERE id_feature_value = 212;

How to choose how to fetch relationships from a relational database?

I know of at least 4 ways of fetching relationships from a relational database.
I tried to make the examples generic to any language.
I'd like to know some algorithm of choosing one over the other besides manually testing the query.
Method A: has the problem of having to loop twice to build the result. also can't process one row at a time one by one without building arrays.
for contact in query("SELECT id, name FROM contact") {
contacts[contact.id]["name"] = contact.name
push(ids, contact.id)
}
for email in query("SELECT contact_id, address FROM email WHERE contact_id IN ?", ids) {
push(contacts[email.contact_id]["emails"], email.address)
}
Method B: Has the problem of a cartesian join in case of more joins
for contact in query("SELECT c.id, c.name, e.address FROM contact c JOIN email e ON e.contact_id = c.id") {
contacts[contact.id]["name"] = contact.name
push(contacts[email.contact_id]["emails"], email.address)
}
Method C: Has a problem in that GROUP_CONCAT is limited to a certain number of bytes and might be cut off
for contact in query("SELECT c.id, c.name, GROUP_CONCAT(e.address) AS addresses FROM contact c JOIN email e ON e.contact_id = c.id GROUP BY c.id") {
contacts[contact.id]["name"] = contact.name
contacts[contact.id]["emails"] = split(",", contact.addresses)
}
Method D: Has the N+1 query problem, runs a query for each contact
contactStatement = prepare("SELECT id, name FROM contact")
emailStatement = prepare("SELECT address FROM email WHERE contact_id = ?")
for contact in contactStatement.query() {
contacts[contact.id]["name"] = contact.name
// this uses a prepared query
for email in emailStatement.query(contact.id) {
push(contacts[contact.id]["emails"], email.address)
}
}
Or maybe there is a way that is ideal in every case?
I have many years of experience using various ORM's and I'd like to avoid using one.
Method A is what most ORM's default to.
Method D is what seems like the solution that SQL designers expect us to use.
I'm asking for some help in how to find a logical way of picking one method over another for a specific SQL query.

Codeigniter active record query count

in my project i have 4 tables. One called Calls, Projects, Products and Users.
Calls has 2 FK (project_id and user_id) and Projects has one FK (product_id).
I'm trying to query the table Calls and I want to know the amount of calls for each product has been received from each operator.
I'm trying to query something like this:
[{"name":"User1","Project1":"120","Project2":"10,"Project3":"140...}
{"name":"User2","Project1":"80","Project2":"60,"Project3":"14...}]
I am guessing when you mean operator you mean user
$this->db->select('count(P.product_id) as total_product ,CL.project_id, CL.user_id, P.project_name')
->from('Calls CL')
->join('Projects P', 'P.project_id=CL.project_id')
->group_by('CL.project_id, CL.user_id')
->get();
Now your can write a php script to loop through your result to make the json
$index = 0;
$user_data = array();
$user_key = array();
foreach ($result as $row) {
if(!isset($user_key[$row['user_id']])){
$user_key[$row['user_id']] = $index;
$index++;
}
$user_data[$user_key[$row['user_id']]]['user_name'] = $row['user_name'];
$user_data[$user_key[$row['user_id']]][$row['project_name']] = $row['total_product'];
}
I did not tested the code but it should work

SQL order by list

Here is part of code for favourited wallpapers:
...
$profile = mysql_fetch_array(mysql_query("SELECT * FROM users WHERE id = $id"));
}
if ($profile['favourites'] != '') {
$from = (($page * $template['fav_wallpaper_limit']) - $template['fav_wallpaper_limit']);
$favourites = substr($profile['favourites'], 2);
/// Tried to join 2 tables, but favourites still displayed by wallpaper id
$sql = mysql_query("
SELECT
*
FROM
wallpapers AS w
JOIN favourites AS f on f.wallpaper_id = w.id
WHERE
w.id IN ($favourites) AND w.published = 1
ORDER BY
f.wallpaper_id LIMIT $from, $template[fav_wallpaper_limit]");
");
Problem is, that it displays wallpapers by the id column that is stored in wallpapers table. While I need to display them by how they wore favourited. The data is stored in users table, and have column favourites for each user with id list of favourited wallpapers.
EXAMPLE:
, 90, 2031, 1, 34, 460, 432, ..., 2013;
Is there any way do grab this tada and order favourites from it?
I think you need to do this within your PHP code:
Read the value of the favourites column;
Explode it into an array;
Iterate through the array, querying the database to get the favourites in the specified order.
The usual way to do this kind of thing is to have a seperate table, say user_favourites with a row for each fovourite for each user that just includes the user id and the favourite id - in this case, with an order factor as well. With the database set up this way, your can execute a query on the new user_favourites table, where user_id is the user id, ordered by the "order factor" to get the favourites in the right order all in one go.
Which database are you using? You might be able to do something like
SELECT _whatever_
FROM favourites
WHERE favourite_id IN (SELECT favourites FROM users)
and it might return the favourites in the correct order. I think the additional table approach is superior, if you can do it that way.

how to create criteria with join in yii

I have to tables, one is profile and the other is rating.
rating has a field profileid which is primary key to profile.id and a field with rating values. Now I want to find the field with highest rating and display the corresponding profile. Since I'm new to YII framework I'm having troubles with it. Please help me getting out of it. What I'm doing is described below.
$topRage=new CDbCriteria();
$topRage->select="*";
$topRage->alias="t1";
$topRage->order="rateing DESC";
$topRage->join="JOIN `ratings` ON `profile`.`id` = `t1`.`profileId`";
$topRage->limit="1";
Try this :
join='JOIN profile ON profile.id = t1.profileId';
If you are doing this: Ratings::model()->findAll($topRage) , then ratings table is already being queried, so you need to join with profile table.
Edit:
for echo you'll need to do this:
$echo "Rating id: ".$rating->id."|&nbspProfile Id: ".$rating->profile->id."|&nbspProfile Name: ".$rating->profile->name."|&nbspRating: ".$rating->ratingvalue;
Don't forget to pass $rating from the controller though.
You could also use find($topRage) instead of the findAll($topRage) and remove the limit, but that 's just another way of doing the same thing.
just query without join .
$topRage=new CDbCriteria();
$topRage->select="*";
$topRage->alias="t1";
$topRage->order="rateing DESC";
$topRage->limit="1";
$rating=Ratings::model()->findAll($topRage);
$profile=Profile::model()->findByPk($rating->profileId);