If I have 2 tables one is users and one is stores , the users id field is associated with the store's user_id field .
Now if I want to find all those users who has a store how can I perform it on readbean ?
and please do explain as I'm just getting started with it.
Thanks
If your queries looking complex, You can simply use plain sql inside redbean.
$records = R::getAll("SELECT * FROM tbl1 LEFT JOIN tbl2 ON tbl1.id = tbl2.tbl1_id");
This will result into and all satisfying records array.
Here I have used R::getAll($your_qry) method, to fetch for single row use R::getRow($yoyr_sql_qry); method.
If you have any difficulties. let me know.
Is it a 1:Many or Many:Many?
If I understand what you said, it's 1:Many
DB model: stores belong to users
So, a store can belong to exactly one (1) user, correct?
If so, it's easy using redbean
$user = R::dispense('users'); // create a user
$store = R::dispense('stores'); // create a store
$store2 = R::dispense('stores'); // create a store
$store1->name = 'Foo';
$store2->name = 'Bar';
$user->xownStoresList[] = $store; // save user ( and store )
$user->xownStoresList[] = $store2; // save user ( and store )
$id = R::store( $user );
foreach ( $user->ownStoresList as $store ) {
echo $store->name . ', ';
}
// outputs: "foo, bar,"
Related
Problem: Searching employees based on document numbers.
Input: List of document nos. and document types
Expected result: list of employees for corresponding document nos AND types.
tables I have:
Table 1:employee
empID - person
Table 2:document
docNo - docType - id
Please note: employee.person.id = doc.parent.id - this is true by database design
Wrote the query like:
SELECT employee
from Employee employee, Document doc
WHERE doc.docType IN :docTypeList
and doc.docNo IN :docNoList
and employee.person.id = doc.parent.id
I know it wont work, because of "doc.docType IN :docTypeList and doc.docNo IN :docNoList", but couldn't think alternative. Any leads to modify the query so that I can handle both docTypeList and docNoList to find employees that matches both of them.
Looks like you just need to join the tables on the ID value and add the right values in your select clause:
SELECT a.employee, b.docType, b.docNo
FROM employee a JOIN document b
ON a.empID=b.id
here is an example using the naming conventions(sort of) you have in your original question:
SELECT emp.employee, doc.docType, doc.docNo
FROM Employee emp JOIN document doc
ON emp.empID=doc.id
Unrelated to your question but when using tablename aliases you should probably shorten the alias otherwise you can just type out the name of the table everytime. The point of an alias is to make your code cleaner and easier to type by using shortened tablenames. See above - I changed employee alias to "emp"
I'm more SQL server so presuming your list parameters are like tableTypes....
SELECT employee
from Employee employee
INNER JOIN Document doc ON doc.parent.id = employee.person.id
WHERE
doc.docType IN ( Select doctype FROM :docTypeList )
and doc.docNo IN (Select doc no FROM :docNoList )
When you need to pass a list of parameters to IN(), the solution is to break down your list and pass each item as a separate parameter to the SQL statement.
Assuming MySQL + PDO:
$paramCount = 0;
$params = []; // holds parameter values
$typesParamNames = $numbersParamNames = []; // parameter names for each list
// document types
foreach ($docTypeList as $val)
{
++$paramCount;
$paramName = ":p{$paramCount}";
$params[$paramName] = $val;
$typesParamNames[] = $paramName;
}
// document numbers
foreach ($docNoList as $val)
{
++$paramCount;
$paramName = ":p{$paramCount}";
$params[$paramName] = $val;
$numbersParamNames[] = $paramName;
}
// build the SQL
$typesSqlFragment = implode(',', $typesParamNames);
$numbersSqlFragment = implode(',', $numbersParamNames);
$sql = "SELECT employee from Employee employee, Document doc WHERE doc.docType IN ($typesSqlFragment) and doc.docNo IN ($numbersSqlFragment) and employee.person.id = doc.parent.id";
$stmt = $dbh->prepare($sql);
// pass the collected parameters values to the prepared statement
foreach ($params as $name => $val) {
$stmt->bindParam($name, $val);
}
// run it
$stmt->execute();
I created a php function to fetch records from a sql table subscriptions, and I want to add a condition to mysql_query to ignore the records in table subscriptions that exists in table removed_items, here is my code;
function subscriptions_func($user_id, $limit){
$subs = array();
$sub_query = mysql_query("
SELECT `subscriptions`.`fo_id`, `subscriptions`.`for_id`, `picture`.`since`, `picture`.`user_id`, `picture`.`pic_id`
FROM `subscriptions`
LEFT JOIN `picture`
ON `subscriptions`.`fo_id` = `picture`.`user_id`
WHERE `subscriptions`.`for_id` = $user_id
AND `picture`.`since` > `subscriptions`.`timmp`
GROUP BY `subscriptions`.`fo_id`
ORDER BY MAX(`picture`.`since_id`) DESC
$limit
");
while ($sub_row = mysql_fetch_assoc($sub_query)) {
$subs [] = array(
'fo_id' => $sub_row['fo_id'],
'for_id' => $sub_row['for_id'],
'user_id' => $sub_row['user_id'],
'pic_id' => $sub_row['pic_id'],
'since' => $sub_row['since']
);
}
return $subs ;
}
My solution is to create another function to fetch the records from table removed_items and set a php condition where I call subscriptions_func() to skip/unset the records that resemble the records in subscriptions_func(), as the following
$sub = subscriptions_func($user_id);
foreach($sub as $sub){
$rmv_sub = rmv_items_func($sub[‘pic_id’]);
If($rmv_sub[‘pic_id’] != $sub[‘pic_id’]){
echo $sub[‘pic_id’];
}
}
This solution succeeded to skip the items in the table removed_items however this solution makes gaps in the array stored in the variable $sub which makes plank spots in the echoed items.
Is there a condition I can add to the function subscriptions_func() to cut all the additional conditions and checks?
Assuming id is the primary key of subscriptions and subs_id is the foreign key in removed_items, then you just have to add a condition to the WHERE clause. Something like this should work :
...
AND `subscriptions`.id NOT IN (SELECT `removed_items`.subs_id FROM `removed_items`)
...
Not related to your problem :
Your code seems vulnerable to SQL injection : use prepared statement to prevent this.
The original Mysql API is deprecated, it is highly recommended to switch to Mysqli instead.
I want to create a search query on MySQL database that will consist of 5 different strings typed in from user. I want to query 5 different table columns with these strings.
When I for example have input fields like:
first name, last name, address, post number, city.
How should I query the database that I dont always get all the rows.
My query is something like this:
SELECT user_id, username
from users
where
a like %?% AND
b like %?% AND
c like %?% AND
d like %?% AND
e like %?%;
When I exchange the AND for OR I always get all the results which makes sense, and when I use AND I get only the exact matches...
Is there any function or statement that would help me with this?
EDIT
The code I use is:
$sql = "select users.user_id, first_name
from users
inner join user_normal_aos
on users.user_id = user_normal_aos.user_id
inner join normal_areas_of_expertise
on user_normal_aos.normal_areas_of_expertise_id = normal_areas_of_expertise.normal_areas_of_expertise_id
where
users.first_name like ? AND
users.kanzlei like ? AND
normal_areas_of_expertise.normal_aoe like ? AND
users.postcode like ? AND
users.city like ?";
$query = $this->db->query($sql,
array(
'%'.$lawyer_name.'%',
'%'.$kanzlei.'%',
'%'.$area_of_expertise.'%',
'%'.$post_code.'%',
'%'.$city.'%')
);
For example use PHP to adjust your query based on what fields you have entered.
$where = array();
$replacements = array();
/* you can also compare if string is not null or not empty...
this is just example using isset */
if (isset($lawyer_name)) {
$where[] = 'users.first_name like ?';
$replacements[] = '%'.$lawyer_name.'%';
}
/* repeat this if again for all your fields .... */
$sql = "..... where ".implode(' AND ', $where);
$query = $this->db->query($sql,
$replacements
);
I'm trying to get the row where all of the user inputs are equivalent but I'm trying to get values from multiple tables.
$query=
"SELECT *
FROM (client OR agent OR admin)
WHERE (first='".$mysqli->real_escape_string($_SESSION['first'])."'
AND last='".$mysqli->real_escape_string($_SESSION['last'])."'
AND password='".$mysqli->real_escape_string($_SESSION['pass'])."')";
is there any way to do this?
<?php
$first = $mysqli->real_escape_string($_SESSION['first']);
$last = $mysqli->real_escape_string($_SESSION['last']);
$password = $mysqli->real_escape_string($_SESSION['pass']);
$query=
"SELECT *
FROM client, agent, admin
WHERE (client.first = '$fist' AND client.last = '$last' AND client.password = '$password')
OR (agent.first = '$fist' AND agent.last = '$last' AND agent.password = '$password')
OR (admin.first = '$fist' AND admin.last = '$last' AND admin.password = '$password')";
This is the way how you could get data, but now you must check in what table data exists and for that you can use mysqli_fetch_field.
Btw, consider option to reorganize database tables, because clients, agents and admin can be stored in one table users with column type or role which represents client, agent or admin. This method is called database normalization. After that your queries and data fetching will be much simpler and faster.
i'm writing a chat app with php/mysql
i have 3 tables: user, room and room_participant with these structures:
user: id, username
room: id, title
room_participant: room_id, user_id
Now i want to get list of all rooms along with list of all participants in each room.
Until now i just select all rooms from room table and iterate through all rooms and select users information out of each entry, which is very inefficient.
Is there any way to combine all these select into only 1 select query?
Not certain about this without testing, but give it a try:
SELECT
room.*,
user.*
FROM room
JOIN room_participant ON room_id = room_participant.id
JOIN user ON room_participant.user_id = user.id
ORDER BY room.id
To deduplicate rooms, use GROUP_CONCAT()
UPDATE GROUP_CONCAT() modified to return id|username
SELECT
room.id, room.name
GROUP_CONCAT(CONCAT(user.id,'|',user.username)) AS userlist
FROM room
JOIN room_participant ON room_id = room_participant.id
JOIN user ON room_participant.user_id = user.id
GROUP BY room.id, room.name
ORDER BY room.id
With the userlist generated by GROUP_CONCAT as id|name,id|name,id|name you can use PHP explode() to separate them.
// Split the list on the commas
$users = explode(",", $userlist);
$final_users = array();
// Then split each on the `|`
foreach ($users as $user) {
$split_user = explode("|", $user);
// Append each as a new associative array to $final_users
$final_users[] = array('id' => $split_user[0], 'username' => $split_user[1]);
}
// Now you have an array of users as id, username
var_dump($final_users);
You may wish to do two queries, and then match things up in whatever is using MySQL, e.g. PHP.
These two:
SELECT id, title
FROM room;
SELECT rp.room_id, rp.user_id, u.username
FROM room_participant AS rp
INNER JOIN user as u ON rp.user_id = u.id;
Or these two:
SELECT id, username
FROM user;
SELECT rp.room_id, rp.user_id, r.title
FROM room_participant AS rp
INNER JOIN room as r ON rp.user_id = r.id;
Which two queries make sense depends on what you're doing with the info really.
You could go a step further and select all three separately:
SELECT *
FROM room;
SELECT *
FROM user;
SELECT *
FROM room_participant;
Note: It's probably better to state the columns, rather than using '*', just in case in the future new columns are added to the table that you're not really interested in for these queries.
Obviously, you'd then have to match everything up in whatever is using MySQL, e.g. PHP. You could create a list of rooms and users from the selected info, and then match them up with something like:
// Use MySQL to populate $roomList from database, then do...
foreach ($roomList as $room)
{
$id = $room['id'];
$title = $room['title'];
$this->roomList[$id] = new Room($id, $title);
}
// Use MySQL to populate $userList from database, then do...
foreach ($userList as $user)
{
$id = $user['id'];
$username = $user['username'];
$this->userList[$id] = new User($id, $username);
}
// Use MySQL to populate $roomParticipantList from database, then do...
foreach ($roomParticipantList as $roomParticipant)
{
$room = $this->roomList[$roomParticipant['room_id']];
$user = $this->userList[$roomParticipant['user_id']];
// You could do one/both of these, depending on requirements.
$room->enterUser($user);
$user->joinRoom($room);
}