I need to display just the last date entry for a person in a table, taken from joined tables.
I only seem to able to display the first entry or all.
Controller
public function session_view($id)
{
$data['main_view'] = 'session_view';
$data['view'] = $this->Swim_model->CRUD_read_session($id);
$this->load->view('load_view',$data);
}
Model
public function CRUD_read_session($sessionid)
{
return $this->db->select('*')
->from('sessionsandswimmers')
->join('child', 'ID = SwimmersID')
->join('swimmersawards', 'PersonID = ID')
->join('awards', 'AwardID = AwardsID')
->order_by('LastName')
->order_by('DateAwarded')
->where('SessionID', $sessionid)
->get();
}
View
foreach ($view->result() as $row)
{
echo '<tr>'.$row->FirstName.'</td><td'.$row->LastName.'</td><td>'.$row->Description.'</td><td>'.$row->DateAwarded.'</td></tr>';
}
Result
As you can see, there are several entries for each person (except 1st).
I need to display just the latest date entry for each person.
So there should only be 4 entries.
Table structure
sessionsandswimmers - each session has 4 swimmers
1 tempid Primary int(11) No None AUTO_INCREMENT
2 SessionID int(11) No None
3 SwimmersID int(11) No None
4 SessionSeasonID int(11) No None
5 Year int(11) No None
6 LocationSS int(11) No None
child - gets the swimmers name
swimmersawards - multiple entries per child
1 PersonID int(11) No None
2 AwardsID int(11) No None
3 DateAwarded date No None
awards - gets the name of the award
change ->order_by('DateAwarded') to ->order_by('DateAwarded','DESC') . Need to specify which type of ordering you want. And for just one entry per person use :
->group_by('FirstName,LastName')
If I understood correctly, the result you displayed is the table structure. Where you want the latest entry by date for each "name". If this is right then follow,
SELECT DISTINCT `name` FROM `<your-joined-tables>` order by `date` DESC
Sorry I am not good with CI's query builder.
Hope it works.
Related
I am trying to create a round robin scenario when new leads come in.
When a lead comes in, the following table named "round_robin" will find the position '1' and send the lead data there
Name Type Attributes Null Default Extra
id int(11) No None AUTO_INCREMENT
on_off text Yes NULL
cname text Yes NULL
position int(11) Yes NULL
email varchar(100) Yes NULL
I have some knowledge of PHP so if some coding I used is way off, thats likely why.
This is the code I've started on.
$round_robin_companies = "SELECT * FROM round_robin";
$position_one = "SELECT position FROM round_robin WHERE postion = '1' ";
$query = "SELECT * FROM round_robin WHERE position = '$position'";
$result = mysql_query($query);
if ($result === 1) exit();
else {
UPDATE $position_one SET position='$row_count';
while ($query <= $row_count) {
$row_count++;
}
}
Basically, when a new row is added in a table called leads, I need Company One position to change to $row_count (3) and all the remaining positions to increment down one.
So Company Two position would be 1 and be next in the queue and Company Three would become 2. I want to use row count because I will be adding more companies in the future.
id on_off cname position email
1 on Company One 1 C1#email.com
2 on Company Two 2 C2#email.com
3 on Company Three 3 C3#email.com
So I have same problems with my query. I havent use JOIN so far so I am pretty sure I have something wrong with it but not sure. I have tried this for hours and can not understand - It seems that code is correct but I do not get desired results.
Here are my two tables:(wrote them by hand so If there is some error dont bother)
CREATE TABLE messages (
msg_id INT(11) PRIMARY KEY,
sender_id INT(11),
msg text,
conversation_id INT(11),
seen datetime,
)
CREATE TABLE conversations (
conversation_id INT(11) PRIMARY KEY,
user1_id INT(11),
user2_id INT(11),
requested datetime,
)
I am working now on notification module. I want to get list of conversation_id where user with $user_id have at least one unread message so that I could notify to him that you have new messages in conversation #:
public function getMsgNotifications($user_id)
{
$this->db->select('conversations.conversation_id');
$this->db->distinct('conversations.conversation_id');
$this->db->from('conversations');
$this->db->join('messages','conversations.conversation_id = messages.conversation_id','INNER');
$this->db->where('conversations.user1_id', $user_id);
$this->db->or_where('conversations.user2_id', $user_id);
$this->db->where('messages.sender_id !=', $user_id);
$this->db->where('messages.seen', '');
$query = $this->db->get();
return $query->result();
}
However I get absolutelly random results. I have spent hours looking at values in database and trying to understand problem but the results I get has no patern.
Would appreciate if someone could point out where there are mistakes in my query.
Trying to make a loop for EditableGrid code.
This is how it looks now.
$grid->addColumn('id', 'ID', 'integer');
$grid->addColumn('site', 'Site', 'string');
So if I need to add a new column to the page, I add a new column in MySQL database and also add a new row in this code, like:
$grid->addColumn('newcolumn', 'A brand new column', 'string');
In order to automatically add new columns to the page I want to make a loop, which gets inputs for the first argument (name of the field in the database) taken from the table:
CREATE TABLE price (
id INT(11) NOT NULL AUTO_INCREMENT,
site VARCHAR(50) NOT NULL,
and the other two arguments (label that will be displayed in the header and data type of the column in MySQL) taken from this table:
CREATE TABLE header (
header_name VARCHAR(50) NOT NULL,
header_type VARCHAR(50) NOT NULL,
Ok, think I found the solution. In order to create the loop, we create 2 queries, which are:
$get=$mysqli->query('SELECT header_name, header_type FROM header');
$get1=$mysqli->query('SHOW COLUMNS FROM price');
then we make a loop
while($row = mysqli_fetch_assoc($get) and $row1 = mysqli_fetch_assoc($get1)){
$grid->addColumn(''.$row1['Field'].'', ''.$row['header_name'].'', ''.$row['header_type'].'');}
I, guess, that's it. Also, if you need to exclude some of the columns, use this piece of code:
if($row1 == 'id' || $row1 == 'site')
continue;
Please, read the question carefully before you mark it as duplicate. It is not.
I have a table named questions, and I have field questionMetaTags in that table which accepts coma separated values (keywords)
Here is my table:
`questionID` int(11) NOT NULL AUTO_INCREMENT,
`questioncategoryID` int(11) NOT NULL,
`questionstatusID` int(11) NOT NULL,
`organizationID` int(11) NOT NULL,
`legalformID` int(11) DEFAULT NULL,
`questionProtocolID` varchar(45) DEFAULT NULL,
`questionDisplayedRecordID` int(11) NOT NULL,
`questionTitle` text NOT NULL,
`questionSummary` text,
`questionText` longtext NOT NULL,
`questionAnswerSummary` text,
`questionAnswerText` longtext,
`questionMetaTags` text,
`questionAskedBy` int(11) NOT NULL,
`questionAnsweredBy` int(11) DEFAULT NULL,
`questionAskedOnDate` datetime NOT NULL,
`questionAnsweredOnDate` datetime DEFAULT NULL,
`questionAskedFromIp` varchar(255) NOT NULL
I am trying to create a query which will "produce" related questions. I am displaying one specific question on my page, and I want bellow to display only the questions that:
1. Belong to same category
AND
2. Have at least 2 or more same keywords
In those 2 variables I am holding the category and the keywords of the displayed question, and I would now like to build the query which will display "related" questions.
$keywordsInQurrentQuestion (array that holds the keywords)
$questioncategoryID (category of the question)
I am trying with something like:
SELECT *
FROM question WHERE `questionstatusID` = 5
AND questioncategoryID = $questioncategoryID
// I have no idea how to check if the question have at least 2 keywords that exists in the $keywordsInQurrentQuestion array
");
I have found answers on how to use array in where clause since I want to check for at least 2 same keywords, those answers are not helpful to me.
Your database schema is not really made for that kind of queries. MySQL is a relational database after all.
Solution in MySQL (change of DB schema required)
It would be better to have an extra table for just keywords (or meta tags):
ID tag
1 oranges
2 apples
... ...
154 motor oil
A second table would then hold the relations between questions and tags:
questionID tagID
1 1
1 2
1 37
2 3
... ...
18 102
19 154
Now, when querying for a similar/related question, you can do so by checking your minimum of identical tags. First, a subquery is used to get all tags from your displayed question:
SELECT tagID FROM relations WHERE questionID = 123;
This will then be used in the actual query that retrieves the similar questions:
SELECT DISTINCT(r1.questionID)
FROM relation r1
INNER JOIN relation r2
ON r1.questionID = r2.questionID AND NOT r1.tagID = r2.tagID
WHERE r1.tagID IN (SELECT tagID FROM relations WHERE questionID = 123)
AND r2.tagID IN (SELECT tagID FROM relations WHERE questionID = 123)
This query joins the relation table with itself (selfjoin), looking for rows with an identical question ID but different tag IDs. In the WHERE clause it checks if both joined tags are within the set of the original question. Finally, it will remove all duplicates (DISTINCT) and give you a list of related question IDs.
This query still has to be expanded to check for the category, this has been left out to make the statement clear.
Solution in PHP
According to your comment, you do not want to change the DB schema. Although retrieving all questions from the database first and then get the related ones in PHP might not be the best choice in terms of execution time and performance, it is still possible.
Assuming you have all terms of your original question in some value
$meta_tags = "oranges,apples,avocados,olive oil";
and all your questions from the same category in an array containing at least the question ID and the respective keywords
$questions = array(
0 => array(
"questionID" => 1,
"metaTags" => "apples,olive oil",
),
1 => array(
"questionID" => 2,
"metaTags" => "oranges,motor oil",
),
2 => array(
"questionID" => 3,
"metaTags" => "oranges,avocados",
),
...
);
you can loop through your questions, check if at least two keywords are identical and then store the question IDs in some array:
function check_tags($needles, $haystack) {
$original_tags = explode(',', $haystack);
$original_tags = array_map('trim', $original_tags);
$tags_to_check = explode(',', $needles);
$tags_to_check = array_map('trim', $tags_to_check);
$count = 0;
foreach ($tags_to_check as $t) {
if (in_array($t, $original_tags)) {
count++;
}
}
return $count;
}
$related = array();
foreach ($questions as $q) {
if (check_tags($q['metaTags'], $meta_tags) >= 2) {
$related[] = $q['questionID'];
}
}
The array $related now contains all question IDs which are similar to your original question.
I have a question if anyone can answer. Please excuse my inexperience with this, but this is my first project that I have attempted and all of this is really new to me. I am in the process of trying to build an inventory system at work using php and mySQL and I have hit a bit of a wall regarding how I am going to display the items that are currently loaned out to people.
I have the items that are being provisioned to users broken down into 4 categories and records of the loans for these items are stored into 4 different tables. I also have another table for users, as well as tables for the items, and their characteristics.
What I want when my page is displayed to to have all of the items that are assigned to each user grouped together in a table. I have two ideas on how I can do this, but I'm not sure which would be the best way.
My first thought was to pull all of the users from the users table and store the information into an array, then pull all of the information from the 4 loan tables and store each table into an array. From there I would do something like
for($i=1;$i>sizeof($usersArray);$i++){
for($a=1;$a>sizeof($loanTable1Array);$a++){
if($userArray[$i][userID] == $loanTable1Array[$a][userID]{
//list items
}
}
for($b=1;$b>sizeof($loanTable2Array);$b++){
if($userArray[$i][userID] == $loanTable2Array[$b][userID]{
//list items
}
}
for($c=1;$c>sizeof($loanTable3Array);$c++){
if($userArray[$i][userID] == $loanTable3Array[$c][userID]{
//list items
}
}
for($d=1;$d>sizeof($loanTable4Array);$d++){
if($userArray[$i][userID] == $loanTable4Array[$d][userID]{
//list items
}
}
}
My concern with this though is that I will have around 100-150 users and each table will have an average of 100 different items. This would mean around 40,000 - 60,000 iterations of the loop.
My other idea was to do pull all of the entries from the user table, then use that data to query the other 4 tables using the userID in a where statement like this. But then I read that if you have a query in a loop then you're doing it wrong.
$sql = "SELECT userID FROM users";
$allUsers = runQuery($sql); //data is sanitized before running the query
for($i = 1; $i<sizeof($allUsers); $i++){
$loan1sql = "SELECT * FROM loantable1 WHERE userID = {$allUsers[$i][$userID]}'";
$loan1Items= runQuery($loan1sql);
for($a = 1; $a<sizeof($loan1Items); $a++){
//list items
}
$loan2sql = "SELECT * FROM loantable2 WHERE userID = '{$allUsers[$i][$userID]}'";
$loan2Items= runQuery($loan2sql);
for($b = 1; $b<sizeof($loan2Items); $b++){
//list items
}
$loan3sql = "SELECT * FROM loantable3 WHERE userID = '{$allUsers[$i][$userID]}'";
$loan3Items= runQuery($loan3sql);
for($c = 1; $c<sizeof($loan3Items); $c++){
//list items
}
$loan4sql = "SELECT * FROM loantable4 WHERE userID = '{$allUsers[$i][$userID]}'";
$loan4Items= runQuery($loan4sql);
for($d = 1; $d<sizeof($loan1Items); $d++){
//list items
}
}
Doing this would result in 400 - 600 calls to the database each time the page is loaded. Does anyone have any input on what my best course of action would be? Any help would be greatly appreciated.
By considering an extra category column , you could have one loantable instead of four . Then you would just use one query by JOINing the tables .
Just an example showing one way to do it :
-- Table structure for table `users`
CREATE TABLE IF NOT EXISTS `users` (
`userID` int(11) NOT NULL AUTO_INCREMENT,
PRIMARY KEY (`userID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
-- Dumping data for table `users`
INSERT INTO `users` (`userID`) VALUES
(1),
(2);
-- --------------------------------------------------------
-- Table structure for table `loantable`
CREATE TABLE IF NOT EXISTS `loantable` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`category` int(11) NOT NULL,
`userID` int(11) NOT NULL,
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 ;
-- Dumping data for table `loantable`
INSERT INTO `loantable` (`ID`, `category`, `userID`) VALUES
(1, 1, 1),
(2, 2, 1),
(3, 3, 1),
(4, 1, 2),
(5, 3, 2);
Then you would use just one query like :
SELECT *
FROM
`users`
LEFT OUTER JOIN loantable ON loantable.userID = users.userID
WHERE 1
ORDER BY
users.userID
,category
(refer to answers above. This was too long to add as a comment, but I thought it would be helpful)
#cartalot and #Uours THANK YOU!!!! - I had considered creating one table for all of the loans early on but didn't know how to implement it. This makes perfect sense though. My whole issue was confusing the foreign key - parent key constraints in mySQL with how you can actually join tables to display information on your page.
Not to sound like a complete moron, but I think this might be constructive to someone that reads this down the road. I got confused by how you can create fk - pk relations in myPHPAdmin and what they actually do. I though that these relations were necessary to join tables (obviously wrong). I saw the visual connections and though that these tables were somehow "connected".
I know understand that when you create a foreign key parent key restraints all you are basically doing is limiting they data that you can enter into a table based on what is in another table. You can still join information from different tables without these constraints.