How can I get the nearest rows in mysql? - php

Lets say I'm trying to build a thumbnail of some gallery (5 thumbnails showing). How can I get my mysql to display 5 thumbnails, the middle thumbnail will be the image blown up, and the two on the left of the middle will be previous images, and the two other images on the right of the middle will be 2 more images after.
EDIT
I know how to easily get 5 thumbnails with something like this
$sqlThumb = mysql_query("SELECT iID,thumbnails,userID FROM images WHERE userID = ".$_SESSION['userID']." ORDER BY iID ASC LIMIT 1,5");
But the thing is, I dont have a consistent id (meaning, there will be deleting and inserting). It is based on the images that the user has.
iID userID
----- --------
1 5
2 4
3 4
4 5
5 5
6 5
10 5
11 5
12 5
So if a user clicks an image which shoes iID number 5, the thumbnail should show like this in order, 1,4,5,6,10.
However, also if a user clicks on thumbnail number 10, the thumbnail should show: 5,6,10,11,12.

Try this
$offset = $current_id-3;
(SELECT * FROM TBL WHERE id < '$current_id' limit '$offset',2 )
union( SELECT * FROM TBL WHERE id = '$current_id')
union (SELECT * FROM TBL WHERE id > '$current_id' limit 2)

I don't know if this works, but the idea is to have an attribute called row_number. You will get the image you want by the id and the two last and the two next by the row number.
SELECT iID,thumbnail FROM image_collection,
(SELECT iID, thumbnail, row_number
FROM
(SELECT iID,thumbnail,
#curRow := #curRow + 1 AS row_number
FROM image
WHERE userID = 5
ORDER BY iID) as image_collection
WHERE s_image.iID = 10) as image_selected
WHERE image_collection.row_number BETWEEN image_selected.row_number - 2 AND image_selected.row_number + 2
I don't tested it because I don't have MySQL running, but I see how to put the row number here: With MySQL, how can I generate a column containing the record index in a table?

Try this one (doesn't include any subtraction):
$id = 5;
$user_id = $_SESSION['userID'];
$sqlThumb = mysql_query("
SELECT iID FROM images WHERE userID = ".$user_id." AND iID = ".$id."
UNION (SELECT iID FROM images WHERE userID = ".$user_id." AND iID < ".$id." ORDER BY iID DESC LIMIT 2)
UNION (SELECT iID FROM images WHERE userID = ".$user_id." AND iID > ".$id." ORDER BY iID ASC LIMIT 2)
ORDER BY iID ASC")

Related

Mysql query to retrieve single image from an array of images?

Table to store array of Images:
`products` and `products_photos`
`products` includes only `id` field
`products_photos` includes `product_id` and `filename`
Table values:
products
--------
id-6
id-7
products_photos
---------------
6 - filename1
6 - filename2
7 - filename3
In these two table id 6 includes 2 images but i need to fetch only one image from that. How to write a query for that in mysql or laravel.
If you want to get the latest (last added) image of the product then you can do the following way
NOTE : Instead of *, use the precise columns so that your query performs faster.
SELECT * FROM products_photos WHERE product_id = 6 ORDER BY products_photos.id DESC LIMIT 1;
If you want to get the first (old added) image of the product then you can do the following way
SELECT * FROM products_photos WHERE product_id = 6 ORDER BY products_photos.id ASC LIMIT 1;
Updated : Query to get the list of all the records group
SELECT MAX(id) as id, photo_name FROM products_photos GROUP BY photo_name
In case if you have more than one columns and want to get the latest record for that too then go for this
Eg. Considering that your having description column and want to get the MAX (latest) content than use MAX, if you need oldest use MIN
SELECT MAX(id) as id, photo_name, MAX(description) as description FROM products_photos GROUP BY photo_name
You can give limit to your query to get single result
SELECT * FROM products_photos WHERE product_id = 6 ORDER BY id LIMIT 1;
Which will give single image only for id = 6 product
For retrieve all data use group by
SELECT * FROM GemSellerPortal.products pr
LEFT JOIN GemSellerPortal.products_photos ph
ON ph.product_id = pr.id
GROUP BY pr.id

MYSQL sort the next row with the UploadDate when Wilson score interval are equal

I'm working on my photo gallery and I have a filter to sort my media with a Wilson score interval. This score is saved in a field of my table called score
For this query I use the following fields : id, UploadTime, score
The issue I am having is that some scores will be exactly the same if lets say if mulitple picture have only one thumb up. In that case I would like to sort the media by the UploadDate field, make the older picture less relevant.
This is my script to sort out all my picture (keep in mind that the score must me higher than 0 to get in the list)
SELECT *
FROM photos
WHERE status = 0
AND score > 0
ORDER BY score DESC, id DESC
Then for getting the next picture (the next picture is a picture with a lower score or if score is equal output the latest one uploaded). And the $id is the unique id of the current picture
SELECT *
FROM photos p
INNER JOIN
(
SELECT score, id
FROM photos
WHERE id = ".$id."
) p2 ON p.score < p2.score
WHERE p.status = 0 AND p.net_votes > 0
ORDER BY p.score DESC, p.UploadTime DESC
LIMIT 1
I have used up all my ideas on how to do this.
I'm not entirly sure (I might have gotten a > instead of < somewhere). Hopefully this will work
SELECT *
FROM photos
WHERE status = 0
AND net_votes > 0
AND ( score < (SELECT p1.score
FROM photos p1
WHERE p1.id = :id)
OR uploadtime < (SELECT p2.uploadtime
FROM photos p2
WHERE p2.id = :id) )
ORDER BY score DESC,
uploadtime DESC
LIMIT 1

Ordering the SQL query in a particular order

Say i have a table Guest and it has column g_id : values 1 to 10.
Now i want the query to return me the g_id's neither in ascending order nor in descending..
but i want the 4th then 3rd and then 5th entry, in this particular order.
Also i want just the 4th 3rd and 5th entry.
say my entries have an id and a name . ;i.e. my table Guest has these two tables.
Now my table is as following.
1 A
2 B
3 C
4 D
5 E
6 F
7 G
8 H
9 I
10 J
Now i want just the entry with 4th 3rd and 5th g_id, and in this particular order.
How do i write the SQL query?
Thanks.
Select * from Guest ___________???
Kindly fill in the gaps.
You can use a CASE statement in your ORDER BY to use a fake column to sort on and a WHERE IN clause to only return the values you need.
SELECT *
FROM Guest
WHERE g_id IN (3, 4, 5)
ORDER BY
CASE WHEN g_id = 4 THEN 1
WHEN g_id = 3 THEN 2
WHEN g_id = 5 THEN 3
END
What is the order that deteremines whether something is 4th, 3rd or 5th? Without an ORDER BY clause, the data is returned in an indeterminate order by SQL. You cannot rely on the order that rows are entered or stored in the database table itself.
You can hard-code what you are asking like this:
select *
from Guest
order by case
when g_id = 4 then 1
when g_id = 3 then 2
when g_id = 5 then 3
else 4
end
One solution is the case statement:
select g_id from (
select g_id, case g_id
when 4 then 1
when 3 then 2
when 5 then 3
else 0
end virtcol
where virtcol != 0
order by virtcol
);
I'm not sure how set your ordering will be, but you can order by specifics:
ORDER BY
g_id = 4 DESC,
g_id = 3 DESC,
g_id = 5 DESC
You may be better off selecting the entries as they are and doing something like this in your php code:
$order = array('4 ', '3 ', '5 ');
$data = array();
while ($row = $result->fetch()) {
$data["$row->g_id "] = $row;
}
$data = array_merge(array_flip($order), $data);
I think that the answer mostly depends on the DBMS you are working on.
In Oracle the query below, even though inefficient, should work
select * from
(select * , rownum as order from guest order by id asc ) b
where b.order = 4
UNION
select * from
(select * , rownum as order from guest order by id asc ) b
where b.order = 3
UNION
select * from
(select * , rownum as order from guest order by id asc ) b
where b.order = 5
Not sure if something of more efficient is possible with a simple query,
i would use the monster above only and only if the table you are querying is very small.
You also have another option if the table is big and you have to extract only the first rows. In the case you described, I would retrieve the first 5 rows and then programmatically I would extract the rows in position 4,3,5.
you can extract the first 5 rows with this query in oracle
select * from guest order by id asc where rownum < 6
This query will get you the 3rd, 5th, and 4th items (limit 2, 1 means "retrieve starting with 3rd item, with total number retrieved = 1 records)
(select g_id from Guest limit 2,1)
UNION (select g_id from Guest limit 4,1
UNION (select g_id from Guest limit 3,1)

PHP / MySQL Checking data between tables with long query

This is a more detailed question as my previous attempt wasn't clear enough. I'm new to MySQL and have no idea about the best way to do certain things. I'm building a voting application for images and am having trouble with some of the finer points of MySQL
My db
_votes
id
voter_id
image_id
_images
id
file_name
entrant_id
approved
_users
id
...
Basically I need to do the following:
tally up all votes that are approved
return the top 5 with the most votes
check if the user has voted on each of these 5 (return Boolean) from another table
I've tried variations of
SELECT i.id, i.file_name, i.total_votes
FROM _images i WHERE i.approved = 1
CASE WHEN (SELECT count(*) from _votes v WHERE v.image_id = i.id AND v.voter_id = ?) > 0 THEN '1' ELSE '0' END 'hasvoted'
ORDER BY i.total_votes DESC LIMIT ".($page*5).", 5
is that something I should try and do all in one query?
This query was working fine before I tried to add in the 'hasvoted' boolean:
SELECT id, file_name, total_votes FROM _images WHERE approved = 1 ORDER BY total_votes DESC LIMIT ".($page*5).", 5
At the moment I'm also storing the vote count in the _images table and I know this is wrong, but I have no idea about how to tally the votes by image_id and then order them.
Let me give this a shot to see if I understand your question:
SELECT i.*,(SELECT COUNT(*) FROM _votes WHERE i.id = image_id) AS total_votes, (SELECT count(*) from _votes where i.id = image_id and user_id = ?) as voted FROM _images AS i WHERE i.approved = 1

MYSQL: Query to get previous and next video ID?

I am developing a video website (PHP - MYSQL), just like youtube, in which I want to provide the functionality of Next video and Previous video. Let's say I am currently on videoId: 234 so Next and Previous video links will point to videoId: 233 and 235 respecively.
My table structure is as follows:
videoId videoName videoURL IsActive
-----------------------------------------------------
1 Love world love-world 1
2 Hello world hellow-world 1
3 World news world-news 0
4 The web the-web 1
5 Google web google-web 1
6 Internet internet 1
IsActive a bool (0,1) type column is basically tells that video is viewable on website or not. If its 0 - notviewable and 1 - viewable
Now there are two type of situations which I though are:
When I am browsing through videoId: 4 then I want to run a query to get the the next and previous video id means 2 and 5 respectively, 3 is not because it is disabled.
Other condition would be When I am browsing through videoId: 1 then query should return only one record which is 2, because there is no previous record, same in the case of last record.
Please tell me how to make query for this?
Thanks
I think you could use something like:
SELECT *
FROM videos AS c
WHERE (VideoId = (SELECT MAX(VideoId) FROM videos WHERE VideoId < c.VideoId AND IsActive = 1)
OR VideoId = (SELECT MIN(VideoId) FROM videos WHERE VideoId > c.VideoId AND IsActive = 1))
I'd use
SELECT * FROM videos WHERE videoId > :id AND IsActive = 1 LIMIT 1
UNION
SELECT * FROM videos WHERE videoId < :id AND IsActive = 1 LIMIT 1
This will get the next one
$stmt = $PDO->prepare("SELECT * FROM vedios WHERE vedio > :id AND IsActive = 1")
$stmt->execute(array("id" => $id));
$all = $stmt->fetchAll(PDO::FETCH_ASSOC);
And change > to < for previous. If count($all) return 0, then you don't have a next/previous video.
Try this. Completely untested, but this will give you a normal row with two additional columns 'nextID' and 'prevID'. If one of them is null, then there isn't one.
SELECT v.*, n.id AS nextID, p.id AS prevID
FROM vedios v
LEFT JOIN (SELECT vn.id FROM vedios vn WHERE vn.id > v.id AND isActive = 1 ORDER BY id ASC LIMIT 1) n
LEFT JOIN (SELECT vp.id FROM vedios vp WHERE vp.id < v.id AND isActive = 1 ORDER BY id DESC LIMIT 1) p
If you have any issues / errors with it, let me know and I'll test it properly.
best query string :
SELECT
(SELECT MAX(`id`) FROM `table` WHERE `id` < `t`.`id`) as `_prev_id`,
(SELECT MIN(`id`) FROM `table` WHERE `id` > `t`.`id`) as `_next_id`
FROM `table` `t`
WHERE `t`.`id` = '1'
LIMIT 1

Categories