I have 3 queries which I run which are nearly identical, the latter two have an AND condition.
Main query:
$mess = $mysqli->prepare("SELECT * from ( SELECT cm.id ,cm.userid,cm.message,cm.voteup,cm.votedown,cm.date
FROM chat_messages cm
INNER JOIN members m ON m.id =cm.userid
INNER JOIN chat_settings cs ON cs.id = cm.room_id
WHERE cm.setting_id = ?
ORDER BY cm.date DESC LIMIT 30 ) ddd
ORDER BY date ASC ");
$mess->bind_param("i", $room);
$mess->execute();
$mess->store_result();
$mess->bind_result($chatid,$chat_userid,$message,$voteup,$votedown,$date);
while($row = $mess->fetch()){
//im fetching here in my <div class='div1' >
}
Then, in the second div I have to add an AND condition:
$mess2 = $mysqli->prepare("SELECT * from ( SELECT cm.id ,cm.userid,cm.message,cm.voteup,cm.votedown,cm.date
FROM chat_messages cm
INNER JOIN members m ON m.id =cm.userid
INNER JOIN chat_settings cs ON cs.id = cm.room_id
WHERE cm.setting_id = ? AND voteup - votedown >= 5
ORDER BY cm.date DESC LIMIT 30 ) ddd
ORDER BY date ASC ");
$mess2->bind_param("i", $room);
$mess2->execute();
$mess2->store_result();
$mess2->bind_result($chatid,$chat_userid,$message,$voteup,$votedown,$date);
while($row2 = $mess2->fetch()){
//im fetching here in my <div class='div2' >
}
Lastly, in the third div I have a slightly different AND condition:
$mess3 = $mysqli->prepare("SELECT * from ( SELECT cm.id ,cm.userid,cm.message,cm.voteup,cm.votedown,cm.date
FROM chat_messages cm
INNER JOIN members m ON m.id =cm.userid
INNER JOIN chat_settings cs ON cs.id = cm.room_id
WHERE cm.setting_id = ? AND votedown - voteup >= 5
ORDER BY cm.date DESC LIMIT 30 ) ddd
ORDER BY date ASC ");
$mess3->bind_param("i", $room);
$mess3->execute();
$mess3->store_result();
$mess3->bind_result($chatid,$chat_userid,$message,$voteup,$votedown,$date);
while($row3 = $mess3->fetch()){
//im fetching here in my <div class='div3' >
}
Everything works BUT doing this near-same query seems clumsy. Is it possible to construct the same thing with only one query? I have used $mess->data_seek(0); but its not helping because I didn't add my condition to the query.
Just go for PhP to filter your data instead of triple query your database. In this case you can figure out to go for this solution because you call 3 times your query with the same parameter :
$mess3 = $mysqli->prepare(" SELECT *
FROM ( SELECT cm.id ,
cm.userid,
cm.message,
cm.voteup,
cm.votedown,
cm.date
FROM chat_messages cm
INNER JOIN members m ON m.id =cm.userid
INNER JOIN chat_settings cs ON cs.id = cm.room_id
WHERE cm.setting_id = ?
AND votedown - voteup >= 5
ORDER BY cm.date DESC LIMIT 30 ) ddd
ORDER BY date ASC ");
$mess3->bind_param("i", $room);
$mess3->execute();
$mess3->store_result();
$mess3->bind_result($chatid,$chat_userid ,$message,$voteup,$votedown ,$date);
while($row = $mess3->fetch()){
$voteup = $row['voteup'];
$votedown = $row['votedown'];
addToDiv1($row);
if( $voteup - $votedown >= 5 ) {
addToDiv2($row);
}
if( $votedown - $voteup >= 5 ) {
addToDiv3($row);
}
}
I will just give an answer based specifically on cleaning up your code. Technically you will still make the 3 calls in this scenario, but it will be cleaner because you include one function only, you don't see the script behind it.
As I mentioned, I am not an SQL aficionado so I can not give a good solution there (maybe you can use GROUP BY and perhaps an OR clause...I don't really know...). If I were to do this, I would do a function that can return all the options:
/core/functions/getChatMessages.php
function getChatMessages($settings,$mysqli)
{
$id = (!empty($settings['id']))? $settings['id'] : false;
$type = (!empty($settings['type']))? $settings['type'] : false;
$max = (!empty($settings['max']))? $settings['max'] : 30;
$mod = '';
// No id, just stop
if(!is_numeric($id))
return false;
// equation one
if($type == 'up')
$mod = ' AND voteup - votedown >= 5';
// equation two
elseif($type == 'down')
$mod = ' AND votedown - voteup >= 5';
$mess = $mysqli->prepare("SELECT * from ( SELECT cm.id ,cm.userid,cm.message,cm.voteup,cm.votedown,cm.date
FROM chat_messages cm
INNER JOIN members m ON m.id =cm.userid
INNER JOIN chat_settings cs ON cs.id = cm.room_id
WHERE cm.setting_id = ? {$mod}
ORDER BY cm.date DESC LIMIT {$max} ) ddd
ORDER BY date ASC");
$mess->bind_param("i", $id);
$mess->execute();
$mess->store_result();
$mess->bind_result($chatid, $chat_userid, $message, $voteup, $votedown, $date);
while($mess->fetch()){
$result[] = array(
'chatid'=>$chatid,
'chat_userid'=>$chat_userid,
'message'=>$message,
'voteup'=>$voteup,
'votedown'=>$votedown
);
}
// Send back the data
return (!empty($result))? $result : array();
}
To use:
// Include our handy function
require_once('/core/functions/getChatMessages.php');
// Store our id for use
$settings['id'] = 100;
// Should get 30 from first select
$voteGen = getChatMessages($settings,$mysqli);
// Should get 30 from second select
$settings['type'] = 'up';
$voteUp = getChatMessages($settings,$mysqli);
// Should get 15 from third select
// Just for the heck of it, I added in a limit settings
$settings['max'] = 15;
$settings['type'] = 'down';
$voteDown = getChatMessages($settings,$mysqli);
Now that you have these stored, just use a foreach loop to place them into your view. The good side of this is that you can call this where ever and when ever since the function only returns data. It allows you to work with the data in a view or non-view situation. Side note, I use PDO, so if there is something ineffective with the way the mysqli is fetching, that will be why. It's probably just best to fetch an assoc array to return...
I have a query that returns close to a 1000 records. Using pagination, I'm showing a 100 records per page. Great...no problem. I can also sort by last name or first name in either ascending of descending order. ok so far. The first page returns records for last name starting with A to C. The problem I'm having is that when I click last name to descend I get records with last name starting with Z. The records at the end of my query, I want to get results going from C to A (what is shown on my first page...repeating the same functionality in each page.
Here is what I got...
$orderColumn = 'lastName';
$orderDirection = 'ASC';
if( isset($_POST["oc"]) && $_POST["oc"] !== '' ) { $orderColumn = $_POST["oc"]; }
if( isset($_POST["od"]) && $_POST["od"] !== '' ) { $orderDirection = $_POST["od"]; }
$per_page = 100;
$query = "SELECT * FROM table as t
LEFT JOIN table_2 as t2 ON t.pk_uID = t2.fk_uID
LEFT JOIN table_3 as t3 ON t3.fk_utID = t2.pk_utID
WHERE t3.fk_utID = 7 and t.interviewed = 0";
$result = $db->query($query);
$count = mysql_num_rows($result);
$total = ceil($count/$per_page);
if ($_GET['page']) {
$page = $_GET['page'];
}
$offset = (($page-1)*$per_page);
$query2 = "SELECT firstName as first, lastName as last FROM table
LEFT JOIN table_2 as t2 ON t.pk_uID = t2.fk_uID
LEFT JOIN table_3 as t3 ON t3.fk_utID = t2.pk_utID
WHERE t3.fk_utID = 7 and interviewed = 0 order by $orderColumn $orderDirection LIMIT $offset, $per_page";
$res = $db-> query($query2);
while($row = mysql_fetch_array($res)){
echo "<span style='display: inline-block; width: 15%;'>$row[first]</span>";
echo "<span style='display: inline-block; width: 15%;'>$row[last]</span>";
}
To what I was saying in comment.. BTW I'm on my mobile phone so this may be unformatted and or take a while...
Select what_you_need
From
( select your_inner_select
From table t
LEFT JOIN table_2 as t2 ON t.pk_uID = t2.fk_uID
LEFT JOIN table_3 as t3 ON t3.fk_utID = t2.pk_utID
WHERE t3.fk_utID = 7 and interviewed = 0 LIMIT $offset, $per_page
ORDER BY $orderColumn ASC
)t
order by $orderColumn $orderDirection
I have a query like this:
$query = "SELECT a.sender_id,
a.recipient_id,
a.form_id, due_date,
a.completed,
f.name,
p.priority,
u.first_name,
u.last_name,
SUM(a.completed) as completed_sum
FROM form_assignments a
JOIN forms f ON (form_id = f.id)
JOIN users u ON (sender_id = u.id)
JOIN priorities p ON (priority_id = p.id)
WHERE recipient_id = '{$_SESSION['user_id']}'
ORDER BY due_date ASC";
And a while loop like this:
$assignment_count = (mysqli_num_rows($result));
$assignments_row = array();
while ($row = mysqli_fetch_array($result)) {
$sender = $row['first_name'] . ' ' . $row['last_name'];
$form_id = $row['form_id'];
$form_name = $row['name'];
$priority = $row['priority'];
$due_date = date('m/d/Y', strtotime($row['due_date']));
$completed = $row['completed'];
$not_done = $assignment_count - $row['completed_sum'];
}
And it's only returning one row. It seems my SUM(a.completed) as completed_sum is causing the issues because the query worked fine before I added it, but I want to add up all the values in completed to use in my $not_done variable.
Can anyone help clarify what I'm doing wrong?
When you use an aggregate function like SUM, all the results will be aggregated into one row unless you use a GROUP BY clause to segregate them. But it looks to me like you don't need a SUM in the first place. Your loop is subtracting this value from a total, so you just need the value from each row -- when you subtract them all you'll have subtracted the total. So just select a.completed rather than SUM(a.completed).
For $not_done, you need to initialize it before the loop:
$not_done = $assignment_count;
Then during the loop you should do a running subtraction:
$not_done -= $row['completed'];
Try this query :
SELECT
a.sender_id,
a.recipient_id,
a.form_id,
a.due_date,
a.completed,
f.name,
p.priority,
u.first_name,
u.last_name,
b.completed as completed_sum
FROM
form_assignments AS a
LEFT JOIN (
SELECT form_id,SUM(completed) FROM form_assignments GROUP BY form_id
) AS b ON (a.form_id = b.form_id)
LEFT JOIN forms AS f ON (form_id = f.id)
LEFT JOIN users AS u ON (sender_id = u.id)
LEFT JOIN priorities AS p ON (priority_id = p.id)
WHERE
recipient_id = '{$_SESSION['user_id']}'
ORDER BY due_date ASC
this my query
function get_transaksi_by_tgl($tgl_awal,$tgl_akhir,$limit, $offset = 0) {
$rs['query'] = $this->db->query("SELECT a.id_transaksi, a.nama, a.tgl_transaksi,
(SELECT COUNT( id_transaksi ) AS jum FROM tbl_detail_trs_menu WHERE id_transaksi = a.id_transaksi)
AS jumlah, a.status_transaksi, a.total, b.status_pelanggan, c.nama_karyawan FROM tbl_transaksi a
LEFT JOIN tbl_pelanggan b ON a.id_pelanggan = b.id_pelanggan LEFT JOIN tbl_karyawan c
ON a.id_karyawan = c.id_karyawan WHERE a.status_transaksi = 'OK' AND a.tgl_transaksi between ".$tgl_awal."
AND ".$tgl_akhir." LIMIT ".$offset.",".$limit."");
echo "jumlah : ".$rs['query']->num_rows();
return $rs;
}
but this query can't return rows....
whereas i try query in database can return 4 row... why??? thx u
How do I change a certain SQL query form inside PHP code Like for example here in the below code
<?php
function eb_mine_views_query_alter(&$view, &$query) {
if ($view->name == 'statuser') {
dsm($query, 'before');
$query->where[0]['type'] = 'OR';
dsm($query, 'after');
}
}
?>
this code is related to a Drupal modification.
previous query
SELECT node.title AS node_title, node.nid AS nid, node.created AS node_created
FROM
{node} node
INNER JOIN {taxonomy_index} taxonomy_index_value_0 ON node.nid = taxonomy_index_value_0.nid AND taxonomy_index_value_0.tid = :views_join_condition_0
INNER JOIN {taxonomy_index} taxonomy_index_value_1 ON node.nid = taxonomy_index_value_1.nid AND taxonomy_index_value_1.tid = :views_join_condition_1
WHERE ((( (taxonomy_index_value_0.tid = :db_condition_placeholder_2) )**AND**( (taxonomy_index_value_1.tid = :db_condition_placeholder_3) )))
ORDER BY node_created DESC
After the above code runs the resulting query
SELECT node.title AS node_title, node.nid AS nid, node.created AS node_created FROM node node OUTER JOIN taxonomy_index taxonomy_index_value_0 ON node.nid = taxonomy_index_value_0.nid AND taxonomy_index_value_0.tid = '9' OUTER JOIN taxonomy_index taxonomy_index_value_1 ON node.nid = taxonomy_index_value_1.nid AND taxonomy_index_value_1.tid = '6' WHERE ((( (taxonomy_index_value_0.tid = '9') )OR( (taxonomy_index_value_1.tid = '6') ))) ORDER BY node_created DESC LIMIT 5 OFFSET 0;
As you can see the query changed from AND to OR.
Now I want to change the same code like this:
SELECT node.title AS node_title, node.nid AS nid, node.created AS node_created FROM node node LEFT OUTER JOIN taxonomy_index taxonomy_index_value_0 ON node.nid = taxonomy_index_value_0.nid AND taxonomy_index_value_0.tid = '9' LEFT OUTER JOIN taxonomy_index taxonomy_index_value_1 ON node.nid = taxonomy_index_value_1.nid AND taxonomy_index_value_1.tid = '6' WHERE ((( (taxonomy_index_value_0.tid = '9') )OR( (taxonomy_index_value_1.tid = '6') ))) ORDER BY node_created DESC LIMIT 5 OFFSET 0;
rather than using OUTER JOIN I want to use LEFT OUTER JOIN. So how do I do this in my PHP code
Try this:
<?php
function eb_mine_views_query_alter(&$view, &$query) {
if ($view->name == 'statuser') {
dsm($query, 'before');
$query->where[0]['type'] = 'OR';
$query->tables[1]['type'] = 'LEFT OUTER';
dsm($query, 'after');
}
}
?>