mongo db group-order - php

i want to mongodb query this sql query's:
select x,y,message,foo from messege where x=1 and y=1 group by x,y order by _id DESC
but with :
MongoCollection::group
can anyone help me?

For this
select a,b,sum(c) csum from coll where active=1 group by a,b
The respective is
db.coll.group(
{key: { a:true, b:true },
cond: { active:1 },
reduce: function(obj,prev) { prev.csum += obj.c; },
initial: { csum: 0 }
});
You cannot sort the results you get from group, you can use sort for find like this for desc -1 , 1 for asc : .sort({"_id":-1}) desc
check this http://www.mongodb.org/display/DOCS/Aggregation#Aggregation-Group

Related

Codeigniter mysql query using UNION to select values equal to today's date first

I want to modify the following query from a model on Codeigniter:
public $table = 'fi_client_notes';
public $primary_key = 'fi_client_notes.client_note_id';
public function default_select()
{
$this->db->select("SQL_CALC_FOUND_ROWS fi_client_notes.*, fi_clients.client_name", FALSE);
if ($this->session->userdata('user_id') <> 1)
{
$this->db->where('fi_clients.user_id', $this->session->userdata('user_id'));
}
}
public function default_order_by()
{
$this->db->order_by('fi_client_notes.client_note_date DESC');
}
public function default_join()
{
$this->db->join('fi_clients', 'fi_clients.client_id = fi_client_notes.client_id');
}
My goal is to select first only the rows where the value "fi_client_notes.client_note_end" is equal to today's date, then show all the rest of the rows arranged in descending order based on the value "fi_client_notes.client_note_date".
This is the query I'm trying:
(SELECT SQL_CALC_FOUND_ROWS fi_clients.client_name, fi_client_notes.* FROM (`fi_client_notes`) JOIN `fi_clients` ON `fi_clients`.`client_id` = `fi_client_notes`.`client_id` WHERE `fi_client_notes`.`client_note_end` = CURDATE())
UNION
(SELECT fi_clients.client_name, fi_client_notes.* FROM (`fi_client_notes`) JOIN `fi_clients` ON `fi_clients`.`client_id` = `fi_client_notes`.`client_id`
ORDER BY `fi_client_notes`.`client_note_date` DESC LIMIT 15)
But I don't know how to use it on Codeigniter, since CodeIgniter's ActiveRecord doesn't support UNION
in this case you can get result without union, just add n.client_note_end <> CURDATE() as top level for order by clause
SELECT c.client_name, n.*
FROM `fi_client_notes` as n
JOIN
`fi_clients` as c
ON c.`client_id` = n.`client_id`
ORDER BY (n.`client_note_end` <> CURDATE()),
`n.`client_note_date` DESC LIMIT 15

SELECT query failing when I added a WHERE statement in it

I had a SELECT query like this at first..
($con,"SELECT * FROM users ORDER BY id ASC LIMIT 1");
But, I realized that I needed the newest user out of the groups 2, 3, 4, or 5 (excluding group 1). So in the end I only want one user showing that is the newest.
What is wrong with my SELECT query now that it would not show up anything?
//Newest Member
$member = mysqli_query($con,"SELECT * FROM users WHERE `group`=2, 3, 4,5 ORDER BY id ASC LIMIT 1");
$numrows_member = mysqli_num_rows($member);
if($numrows_member > 0){
while($row_member = mysqli_fetch_assoc($member)){
$memberid = $row_member['id'];
$member_username = $row_member['username'];
echo $member_username;
}
} else {
echo "No Members Found...";
}
You are looking for the IN operator. The syntax would be like this:
SELECT *
FROM users
WHERE `group` IN (2, 3, 4, 5)
ORDER BY id ASC
LIMIT 1;
There is a reference here.
Note: Based on your comment, if you are looking for the latest user you may want to order in DESC order instead, so that the largest id is put first. Even better (in my opinion), if you store the account_created_date you could order by that. Again, in descending order.
If you want to exclude a specific group, use != instead of trying to find one of the remaining groups:
SELECT * FROM users WHERE `group` != 1 ORDER BY id ASC LIMIT 1

Oracle SQL query returns same set of results despite variation in ROWNUM value

I'm working on a Oracle/PHP application and trying to implement a "load-more" functionality.
Here are the two tables and their structures:
questions:
id (int) | title (varchar(999)) | datetime (varchar(999))
questions_tags:
id (int) | question_id (int) | tag_id (int)
The following is the code in index.php:
$stid = oci_parse($conn, "select * from (
select a.*, ROWNUM rnum from (
SELECT questions.id FROM questions_tags, questions WHERE
questions.id = questions_tags.question_id AND
questions_tags.tag_id IN (1,2,3,4,5,6,7) ORDER BY questions.datetime ASC
) a where rownum <= 10
) where rnum >= 0");
oci_execute($stid);
while (oci_fetch($stid)) {
// Do work with the results
}
The following is the javascript behind it:
$("#load_more").click(function(e) {
$.ajax({
url: "loadMore.php?x=" + $(".span_data:last").data("id"),
success:function(data, textStatus, jqXHR)
{
if (data)
{
// append data
} else {
// remove button
}
},
error: function(jqXHR, textStatus, errorThrown)
{
//if fails
}
});
e.preventDefault(); //STOP default action
});
Finally, here is the loadMore.php file:
<?php
$x = $_GET['x'];
$xTen = intval($x) + 10;
$count_id = $x;
try
{
$lastID = 0;
$tagIDs = implode("','", $user_tag_ids);
$stid = oci_parse($conn, "select * from (
select a.*, ROWNUM rnum from (
SELECT questions.id FROM questions_tags, questions WHERE
questions.id = questions_tags.question_id AND
questions_tags.tag_id IN (1,2,3,4,5,6,7) ORDER by questions.datetime DESC
) a where rownum <= $xTen
) where rnum >= $x");
oci_execute($stid);
while (oci_fetch($stid)) {
// Do work with the results
}
}
catch(Exception $e) {
print "Error";
}
?>
No matter what the value of x is, the loadMore.php file continues to return the same set of results. So if I do /loadMore.php?x=10, I will get the same results as that returned by /loadMore.php?x=100 However, if I go even further (/loadMore.php?x=1500), that's when I finally get different results. I can't understand what's going wrong here.
As I said in the comments:
If I remove all the rownum parameters and just run
SELECT * FROM questions WHERE EXISTS (
SELECT 1 FROM questions_tags WHERE
questions.id = questions_tags.question_id AND
questions_tags.tag_id IN (1,2,3,4,5,6,7)
) ORDER BY datetime DESC
I get all the results, probably a thousand rows. I'm trying to get the first 10 of those thousand rows and then keep getting the next 10 when the user clicks the "load more" button. That's why I have same query index.php and loadMore.php
Thanks to the comments, I realized that ORDER BY questions.datetime wasn't unique enough to sort the result properly. Changing the query to ORDER BY questions.datetime DESC, questions.id DESC fixed the issue and began to show unique results.

PHP Calculate rank from database

I got a little problem, I've got a database, in that database are different names, id, and coins. I want to show people their rank, so your rank has to be 1 if you have the most coins, and 78172 as example when your number 78172 with coins.
I know I can do something like this:
SELECT `naam` , `coins`
FROM `gebruikers`
ORDER BY `coins` DESC
But how can I get the rank you are, in PHP :S ?
You can use a loop and a counter. The first row from MySql is going the first rank,I.e first in the list.
I presume you want something like:
1st - John Doe
2nd - Jane Doe
..
..
right?
See: http://www.if-not-true-then-false.com/2010/php-1st-2nd-3rd-4th-5th-6th-php-add-ordinal-number-suffix
Helped me a while ago.
You could use a new varariable
$i = "1";
pe care o poti folosi in structura ta foreach,while,for,repeat si o incrementezi mereu.
and you use it in structures like foreach,while,for,repeat and increment it
$i++;
this is the simplest way
No code samples above... so here it is in PHP
// Your SQL query above, with limits, in this case it starts from the 11th ranking (0 is the starting index) up to the 20th
$start = 10; // 0-based index
$page_size = 10;
$stmt = $pdo->query("SELECT `naam` , `coins` FROM `gebruikers` ORDER BY `coins` DESC LIMIT {$start}, {$page_size}");
$data = $stmt->fetchAll();
// In your template or whatever you use to output
foreach ($data as $rank => $row) {
// array index is 0-based, so add 1 and where you wanted to started to get rank
echo ($rank + 1 + $start) . ": {$row['naam']}<br />";
}
Note: I'm too lazy to put in a prepared statement, but please look it up and use prepared statements.
If you have a session table, you would pull the records from that, then use those values to get the coin values, and sort descending.
If we assume your Session table is sessions(session_id int not null auto_increment, user_id int not null, session_time,...) and we assume that only users who are logged in would have a session value, then your SQL would look something like this: (Note:I am assuming that you also have a user_id column on your gebruikers table)
SELECT g.*
FROM gebruikers as g, sessions as s WHERE s.user_id = g.user_id
ORDER BY g.coins DESC
You would then use a row iterator to loop through the results and display "1", "2", "3", etc. The short version of which would look like
//Connect to database using whatever method you like, I will assume mysql_connect()
$sql = "SELECT g.* FROM gebruikers as g, sessions as s WHERE s.user_id = g.user_id ORDER BY g.coins DESC";
$result = mysql_query($sql,$con); //Where $con is your mysql_connect() variable;
$i = 0;
while($row = mysql_fetch_assoc($result,$con)){
$row['rank'] = $i;
$i++;
//Whatever else you need to do;
}
EDIT
In messing around with a SQLFiddle found at http://sqlfiddle.com/#!2/8faa9/6
I came accross something that works there; I don't know if it will work when given in php, but I figured I would show it to you either way
SET #rank = 0; SELECT *,(#rank := #rank+1) as rank FROM something order by coins DESC
EDIT 2
This works in a php query from a file.
SELECT #rank:=#rank as rank,
g.*
FROM
(SELECT #rank:=0) as z,
gebruikers as g
ORDER BY coins DESC
If you want to get the rank of one specific user, you can do that in mysql directly by counting the number of users that have more coins that the user you want to rank:
SELECT COUNT(*)
FROM `gebruikers`
WHERE `coins` > (SELECT `coins` FROM `gebruikers` WHERE `naam` = :some_name)
(assuming a search by name)
Now the rank will be the count returned + 1.
Or you do SELECT COUNT(*) + 1 in mysql...

Select top 50 rows from a table, but display oldest to newest?

Can someone advise on how to get around this problem?
I want to call the top 50 rows by id from my SHOUTBOX table, but display them in a div in ascending order (the most recent row (newest) at the bottom)
for example;
most recent row is id 200,
I want to call rows 150 - 200,
display them in the div like;
150,
151,
152,
.
.
.etc
.
.
200 <<< last line in DIV
my PHP code currently looks like this;
$recall=mysql_query("SELECT *, DATE_FORMAT(timepost,'%H:%i:%s') as timepost FROM shoutbox ORDER BY id DESC LIMIT 50");
while($comm=mysql_fetch_object($recall)){
if ($comm->poster == "System"){
print"<font color=#3399FF>$comm->timepost-<strong><a href='profile.php?viewuser=$comm->poster' target='iframecontent'><font color=#3399FF>$comm->poster</font></a></strong>: </font>";
echo replace($comm->post);
echo"<br>";
}
but it returns my data in the div like;
200,
199,
198,
.
.
.etc
.
.
150 <<< last line in DIV
Please can anyone help?
note: I am currently working through all my pages and converting all mySQL queries to PDO
For future reference, if you're converting to PDO there is the exact answer for reading backwards on this page without changing your query. http://www.php.net/manual/en/pdostatement.fetch.php.
For now this will work:
SELECT *, DATE_FORMAT(timepost,'%H:%i:%s') AS timepost FROM (SELECT * FROM shoutbox ORDER BY id DESC LIMIT 50) AS foo ORDER BY id ASC
Ok, try this:
$recall=mysql_query("SELECT *, DATE_FORMAT(timepost,'%H:%i:%s') as timepost FROM (SELECT * FROM shoutbox ORDER BY id DESC LIMIT 50) ORDER BY id ASC");
replace ORDER BY id DESC by ORDER BY id
You have wrong the order command, you have to put ASC instead of DESC Here is your correct query:
$recall=mysql_query("SELECT *, DATE_FORMAT(timepost,'%H:%i:%s') as timepost FROM shoutbox ORDER BY id ASC LIMIT 50");
while($comm=mysql_fetch_object($recall)){
if ($comm->poster == "System"){
print"<font color=#3399FF>$comm->timepost-<strong><a href='profile.php?viewuser=$comm->poster' target='iframecontent'><font color=#3399FF>$comm->poster</font></a></strong>: </font>";
echo replace($comm->post);
echo"<br>";
}
Change your query to:
$recall = mysql_query("SELECT *, DATE_FORMAT(timepost,'%H:%i:%s') as timepost
FROM shoutbox ORDER BY id ASC LIMIT 50");

Categories