Problems with SQL syntax? MAX not working - php

$query="SELECT title, max(postid) FROM post";
postid is a increasing numeric value (1,2,3...). At the moment, the highest value is 49, but It's pulling up 1. It seems to be ignoring the MAX statement.
otherwise everything else is working great.

That's not valid syntax, which engine is running it?
You either need:
SELECT title, max(postid) FROM post GROUP BY title;
to get multiple records, one for each title, showing the max postid for each title, or
SELECT max(postid) FROM post
to get the single max postid from the table.
If you want the highest postid and the title that goes with it, you need
SELECT TOP 1 title, postid FROM post ORDER BY postid DESC
or
SELECT title, postid FROM post ORDER BY postid DESC LIMIT 1
depending on your SQL engine.

One important thing is that the field that is used in MAX function should be INT Type
Then it will give accurate result:
SELECT title, max(postid) FROM post GROUP BY title
Postid should be an integer.

Have you tried:
SELECT title, max(postid) FROM post GROUP BY title
I would have expected whichever sql engine you are using to respond with an error without a group by clause in your statement. However, if the GROUP BY is in some way implied somewhere else in your code, you should remove 'title' from the select clause (since I would expect a 'title' to be associated with only one post anyway). In that case if you simply expect the max postid from the post table your statement should read:
SELECT max(postid) FROM post

Related

PHP + Mysql complicated SQL SELECT query

I was thought how to make a complicated (as I think) SELECT query from table with 3 kind of comments (first - positive comments, second - negative comments and third - neutral comments). Using PHP I would like to SELECT and diplay first negative comments, and right after negative comments diplay all other type of comments. How to diplay them with one SELECT query together with LIMIT that I use to separate for pagination?
Example of table:
id - unique id
type - (value 1-positive, 2-negative, 3-neutral)
text - value
I was thought first SELECT * FROM comments WHERE type='2' ORDER BY id LIMIT 0,100
while(){
...
}
Right after that second
SELECT * FROM commetns WHERE type!='2' ORDER BY id LIMIT 0,100
while(){
...
}
But how use LIMIT for pagination if there is two different SELECT queries?
Use a combination of UNION and LIMIT.
However, you need to determine the bind variables, and specify the number of rows you want to display.
(SELECT * FROM comments WHERE type = '2' LIMIT ?)
UNION
(SELECT * FROM comments WHERE type != '2' LIMIT ?);
SQLFiddle: http://sqlfiddle.com/#!9/6d682/1
Use an IF statement in the ORDER BY clause to change the type 2 to sort first:-
SELECT *
FROM comments
ORDER BY IF(type = 2, 0, type)
LIMIT 1, 20
This will give you all the negative (type 2) comments first, followed by the other comments (whether positive or neutral). You would probably want to add an extra column to the sort just for consistency of display.
I didn't get your case exactly, but I think you may use OR operator to get what you want:
SELECT * from comments WHERE type=2 OR type=-2 ORDER BY type DESC
you can use union to merge group of tables, but you must have the same columns in all the tables, for example:
select commetns,'nagtive' as type from nagtive_tbl limit 10
union
select commetns,'positive' as type from positive_tbl limit 10
union
select commetns,'neutral' as type from neutral_tbl limit 10
this query return table with all the comments from different tables each row contain is type so you can filter it while you building the lists on the client.
I must be missing context, otherwise you would just be fine using:
SELECT * from comments ORDER BY type ASC LIMIT 0,10
So by ordering the type, you'll first get all the items with type 1, followed by 2 and 3.
Just using the limit will chop them in the pieces you want and it will still respect the order.

Is there a way to identify which data has been selected with the sql statement

I have a sql statement:
$feed=$conn->prepare("SELECT * FROM posts WHERE post_by=? OR id=? ORDER BY id DESC LIMIT 10");
$feed->bind_param("ii",$friend['id'],$like[id]);
$feed->execute();
The $friend['id'] is the id of a user's friend, $like[id] is the id of a like by the user's friend.
The posts fetched with this query appear in a page.
What I want is I want to know which all posts have been posted by the user's friends (Which all posts have been fetched using $friends['id']) and which all posts have been liked by the user's friends and appear in the feed(Which all posts have been fetched using $like['id'])
I want to know all possibilities I can try to achieve what I want.
I have tried varying my query with UNION ALL but it shows errors and I could'nt achieve what I want.
Currently there are no errors but I want the user to know how this post appeared in the newsfeed.
Hope you all get a good idea about my question and all types of hacks are also accepted as I want in someway to achieve the result I would also agree to change mt query nature.
Please comment for more info.
Thanks in advance.
SELECT *, post_by = ?postId AS post_by_friend
FROM posts
WHERE post_by = ?postId OR
id = ?friendId
ORDER BY id DESC
LIMIT 10
post_by_friend will be 1 if it matched the first condition, otherwise 0. I haven't benchmarked it, but this method should be faster than StuartLC's UNION suggestion.
What you can do is break the query up on its 'OR' clause into a UNION of two separate queries, and add a marker column to indicate whether the row was found by friend or by like:
SELECT *
FROM
(
SELECT *, 'Friend' AS HowFound
FROM posts
WHERE post_by= ?postId
UNION
SELECT *, 'Like' AS HowFound
FROM posts
WHERE id= ?friendId AND post_by <> ?postId
) x
ORDER BY id DESC
LIMIT 10;
You'll want to exclude rows which match both friend and post classifications from one of the selects, otherwise it will be reported twice (or, otherwise your app will need to combine them).
I'm no PHP guru, but I'm sure there is a way to name the parameters to allow the above exclusion.
The derived table is needed to order and restrict the overall result.

getting last value before i insert a new one from the database

i have a wordpress database table called stats that saves records of one post, actually the data saved is the post score, so i might have post id 1 with score 49, another record for post id 2 with score 59, but the post id is the same, so my question is this,
how will i get the score of the second last post id, in this case 49?
please help, i have searched everywhere and no search answer answer to get this value.
$query = $wpdb->get_row("SELECT * FROM stats WHERE score = MAX(score)");
one way would be:
$query= $wpdb->get_row("SELECT * FROM stats WHERE score < max(score) ORDER BY score DESC LIMIT 1 ")
Where we order them by score and get the first result that is not the biggest score. Might need some syntax tweaks, I have only done postgreSQL for the last year or so

I need to select newest rows from a MySQL database, but verify that I am also returning a row with a given ID

I'm new to this, sorry if the title is confusing. I am building a simple php/mysql gallery of sorts. It will show the newest 25 entries when a user first goes to it, and also allows off-site linking to individual items in the list. If the URL contains an ID, javascript will scroll to it. But if there are 25+ entries, it's possible that my query will fetch the newest results, but omit an older entry that happens to be in the URL as an ID.
That means I need to do something like this...
SELECT * FROM `submissions` WHERE uid='$sid'
But after that has successfully found the submission with the special ID, also do
SELECT * FROM `submissions` ORDER BY `id` DESC LIMIT 0, 25`
So that I can populate the rest of the gallery.
I could query that database twice, but I am assuming there's some nifty way to avoid that. MySQL is also ordering everything (based on newest, views, and other vars) and using two queries would break that.
You could limit across a UNION like this:
(SELECT * FROM submissions WHERE uid = '$uid')
UNION
(SELECT * FROM submissions WHERE uid <> '$uid' ORDER BY `id` LIMIT 25)
LIMIT 25
Note LIMIT is listed twice as in the case that the first query returns a result, we would have 26 results in the union set. This will also place the "searched for" item first in the returned sort result set (with the other 24 results displayed in sort order). If this is not desirable, you could place an ORDER BY across the union, but your searched for result would be truncated if it happened to be the 26th record.
If you need 25 rows with all of them being sorted, my guess is that you would need to do the two query approach (limiting second query to either 24 or 25 records depending on whether the first query matched), and then simply insert the uid-matched result into the sorted records in the appropriate place before display.
I think the better solution is:
SELECT *
FROM `submissions`
order by (case when usid = $sid then 0 else 1 end),
id desc
limit 25
I don't think the union is guaranteed to return results in the order of the union (there is no guarantee in the standard or in other databases).

How do I efficiently select unique row/record data from 2 mysql tables and return one merged result, ordered by timestamp?

Stack:
I'm trying to turn my website's user profile into more of a feed style page. Currently the profile shows some user stats at the top, then the last 10 comments a user submitted (ordered by timestamp descending), then the last 10 posts they have submitted.
What I want to do instead, is have the last 20 "actions" (either comment or post submission) listed in order of the timestamp (so the comments and submissions will be merged together in the list instead of having 2 seperate lists). You know, like a "feed."
The issue is that the comments are pulled from a comments table, and the submissions are pulled from a "submissions" table.
I've solved it in a pretty inefficient way by using a union query to select "comment_id/submission_id", "field the identifies record as a comment or a submission", "timestamp" from both tables.
This gives me a result that tells my the entity id, as well as defines the entity as a comment or a post, by which I can then shoot off another query in a while mysql_fetch_array statement to get the full comment or submission data.
This just seems really dirty to me, since I'm basically querying the tables, finding the rows/records that I need (but ignoring the actual data I need since the different table's columns don't match up as I believe to be necessary for a union query), then going back for the data I ignored the first time with individual queries in a while statement...
Is there a better way to do this that I don't know of?
Additional notes:
Example sql I'm currently using to build the initial result I spoke of above:
select comment_id, datatype, timestamp from comments where userid=3
union all
select content_id, datatype, timestamp from submissions where userid=3
ORDER BY timestamp DESC
Returns a result like this:
commentid datatype timestamp
5201 post 2012-03-27 20:30:40
43761 comment 2012-03-26 21:00:19
43759 comment 2012-03-26 20:59:47
5033 post 2012-03-26 20:57:36
43755 comment 2012-03-26 20:54:57
43745 comment 2012-03-26 16:32:24
Pseudocode I can then use to print out the information onto the profile page:
while ($content_array = mysql_fetch_array($abovequery)){
Individual select query fetching the full row by from either comment table or submission table by id depending on $content_array['datatype'];
echo out relevant data from individual select query onto profile screen in a pretty way;
}
Surely this can be done better?
If you are unable to coerce the columns of the two full queries in such a way that it can all be returned in the UNION then you could join the union result to the comments and submissions tables.
SELECT records.datatype, comments.*, submissions.*
FROM (
(
SELECT comment_id, datatype
FROM comments
WHERE userid=3
ORDER BY timestamp DESC
LIMIT 20
) UNION ALL (
SELECT content_id, datatype
FROM submissions
WHERE userid=3
ORDER BY timestamp DESC
LIMIT 20
)
ORDER BY timestamp DESC
LIMIT 20
) AS records
LEFT JOIN comments
ON records.comment_id = comments.comment_id
AND records.datatype = 'comment'
LEFT JOIN submissions
ON records.comment_id = submissions.content_id
AND records.datatype = 'post'
Alternatively, you could run the two innermost selects with all required fields and then order the final result in PHP.

Categories