Somewhat new to SQL queries and I need a little help with my join.
I am supplied with gid
For each of these I need to grab name from table wp_ngg_gallery
then join in table wp_ngg_pictures and grab field filename limit 1 order DESC by field imagedate
Anyone able to help?
Let me know how / if this works. If you dump both of those tables (out of phpMyAdmin) in a SQL format I will create local databases and give it a run myself (assuming this doesn't work).
SELECT
`wp_ngg_gallery`.`name`,
`wp_ngg_pictures`.`filename`
FROM
`wp_ngg_gallery`
LEFT JOIN
`wp_ngg_pictures`
ON
`wp_ngg_gallery`.`gid` = `wp_ngg_pictures`.`galleryid`
ORDER BY
`wp_ngg_pictures`.`imagedate` DESC
LIMIT
0,1;
This is assuming you need a JOIN. It could probably be done with a decent GROUP BY statement.
I'm going to guess:
select wp_ngg_gallery.name, wp_ngg_pictures.filename
from wp_ngg_gallery, wp_ngg_pictures
where wp_ngg_pictures.galleryid = wp_ngg_gallery.gid
order by wp_ngg_pictures.imagedate DESC
limit 0,1
If there's a specific GID you want, you could do:
select wp_ngg_gallery.name, wp_ngg_pictures.filename
from wp_ngg_gallery, wp_ngg_pictures
where wp_ngg_pictures.galleryid = wp_ngg_gallery.gid
and wp_ngg_gallery.gid = $gid
order by wp_ngg_pictures.imagedate DESC
limit 0,1
(The $gid is valid if you're query is a string in PHP, you didn't say, though, if that's what you're using)
It's not clear if wp_ngg_pictures.galleryid is a foreign key to wp_ngg_gallery.gid but it's the most likely choice given the info you supplied. If it's not (if you can have galleries with no images), you might want to modify the other guy's query (using the outer join) by adding and wp_ngg_gallery.gid = $gid to it.
If you want it for multiple gids (choose the other options for a single one):
SELECT gid,name, a.filename
FROM wp_ngg_gallery
JOIN wp_ngg_pictures a
ON a.galleryid = gid
LEFT JOIN wp_ngg_pictures b
ON a.galleryid = gid
AND b.imagedate > a.imagedate
WHERE b.galleryid IS NULL
AND gid IN (1,2,3)
Related
I want to ask how sql join uses limits on one table
I have searched Google but the query I did was different and that made me confused
$queryAnime = "SELECT *
FROM `anime`
JOIN `episode` ON `anime`.`link` = `episode`.`idanime`
ORDER BY `anime`.`id` DESC
";
$anime = $this->db->query($queryAnime)->result_array();
when I add a limit in the normal way only 1 array appears
I let 'anime' appear all and 'episodes' only show one array
and sorry my English is bad I hope you understand and dabat helps me
If I understand your question correctly, you need to specify the columns you need in the Select statements and not use *, and use a Select Distinct
So for example
SELECT DISTINCT `show_name`,`eposode`
FROM `anime` JOIN `episode`
ON `anime`.`link` = `episode`.`idanime`
ORDER BY `anime`.`id` DESC
I am using yii2 data Provider to extract data from database. Raw query looks like this
SELECT `client_money_operation`.* FROM `client_money_operation`
LEFT JOIN `user` ON `client_money_operation`.`user_id` = `user`.`id`
LEFT JOIN `client` ON `client_money_operation`.`client_id` = `client`.`id`
LEFT JOIN `client_bonus_operation` ON `client_money_operation`.`id` = `client_bonus_operation`.`money_operation_id`
WHERE (`client_money_operation`.`status`=0) AND (`client_money_operation`.`created_at` BETWEEN 1 AND 1539723600)
GROUP BY `operation_code` ORDER BY `created_at` DESC LIMIT 10
this query takes 107 seconds to execute.
Table client_money operations contains 132000 rows. What do I need to do to optimise this query, or set up my database properly?
Try pagination. But if you must have to show large set of records in one go remove as many left joins as you can. You can duplicate some data in the client_money_operation table if it is certainly required to show in the one-go result set.
SELECT mo.*
FROM `client_money_operation` AS mo
LEFT JOIN `user` AS u ON mo.`user_id` = u.`id`
LEFT JOIN `client` AS c ON mo.`client_id` = c.`id`
LEFT JOIN `client_bonus_operation` AS bo ON mo.`id` = bo.`money_operation_id`
WHERE (mo.`status`=0)
AND (mo.`created_at` BETWEEN 1 AND 1539723600)
GROUP BY `operation_code`
ORDER BY `created_at` DESC
LIMIT 10
is a rather confusing use of GROUP BY. First, it is improper to group by one column while having lots of non-aggregated columns in the SELECT list. And the use of created_at in the ORDER BY does not make sense since it is unclear which date will be associated with each operation_code. Perhaps you want MIN(created_at)?
Optimization...
There will be a full scan of mo and (hopefully) PRIMARY KEY lookups into the other tables. Please provide EXPLAIN SELECT ... so we can check this.
The only useful index on mo is INDEX(status, created_at), and it may or may not be useful, depending on how big that date range is.
bo needs some index starting with money_operation_id.
What table(s) are operation_code and created_at in? It makes a big difference to the Optimizer.
But there is a pattern that can probably be used to greatly speed up the query. (I can't give you details without knowing what table those columns are in, nor whether it can be made to work.)
SELECT mo.*
FROM ( SELECT mo.id FROM .. WHERE .. GROUP BY .. ORDER BY .. LIMIT .. ) AS x
JOIN mo ON x.id = mo.id
ORDER BY .. -- yes, repeated
That is, first do (in a derived table) the minimal work to find ids for the 10 rows desired, then use JOIN(s) to fetch there other columns needed.
(If yii2 cannot be made to generate such, then it is in the way.)
This is my query to get model information from one table and a single picture from another table. What changes do I have to make to this query in order for it to get the picture where ORDER BY sort DESC? In the table of the pictures, there is a field by the name "sort". The default value for the field for each row is 0. But one random row has the value of 1. I want to get that particular row. I don't, however, want to use WHERE sort=1 because then even in the case where no row has the sort value 1, one row should still get fetched.
$sql="SELECT tc.id,tc.alias,tc.firstname,tci.imagename
FROM ".$pre."models tc
INNER JOIN ".$pre."model_images tci ON tc.id=tci.userid
WHERE activated=1 AND sex=$sex AND city=$city AND published=1
GROUP BY tc.id ORDER BY firstname ASC";
Thank you in advance!
Solved using:
SELECT tc.id,tc.alias,tc.firstname,
(SELECT imagename FROM ".$pre."model_images WHERE userid= tc.id
ORDER BY sort DESC LIMIT 1) AS imagename
FROM ".$pre."models tc
WHERE tc.activated=1 AND tc.sex=1 AND tc.city=2 AND tc.published=1
ORDER BY tc.firstname ASC
You should place that in your WHERE clause aswell. One t hing to note though is to be carefull with the way you're using the column names. It's better to tell to which table they belong.
So this:
WHERE activated=1 AND sex=$sex AND city=$city AND published=1
Should be:
WHERE tc.activated=1 AND tc.sex=$sex AND tc.city=$city AND tc.published=1
And then simply add the 'sort' column to it:
WHERE tc.activated=1 AND tc.sex=$sex AND tc.city=$city AND tc.published=1 AND tci.sort=1
If no results are returned, then make sure that there are records that meet the required conditions. Because there's nothing wrong with the query. Try to print your query to the screen etc. to see if every variables has a value.
edit:
You should lose the GROUP BY.
SELECT tc.id,tc.alias,tc.firstname,tci.imagename
FROM ".$pre."models tc
INNER JOIN ".$pre."model_images tci ON tc.id=tci.userid
WHERE tc.activated=1 AND tc.sex=$sex AND tc.city=$city AND tc.published=1 AND tci.sort=1
I have two queries, the only difference being the GROUP BY clause
SELECT * FROM `packages_sorted_YHZ` WHERE `hotel_city` = 'Montego Bay'
ORDER BY `deal_score` DESC
LIMIT 0,3;
SELECT * FROM `packages_sorted_YHZ` WHERE `hotel_city` = 'Montego Bay'
GROUP BY `hotel_name`
ORDER BY `deal_score` DESC
LIMIT 0,3;
The first query returns the first result with a deal_score of 75 but the second query returns the first result with the deal_score of just 72.
I would have thought that regardless of the GROUP BY clause, the first result would have the highest deal score possible (75)
The purpose of the GROUP BY clause is to optionally select a unique hotel_name for each result.
Does anyone know what I'm doing wrong here.
Without being able to look at all the data, my best guess is that Group By is merging the data and giving you an arbitrary value that matches the Where clause. This will happen if hotel name isn't unique, and you won't be given the maximum score unless you specifically query for it.
Try putting a Max() around deal_score. In MySQL, Group By can be used way too easily, I like how MSSQL enforces the use of aggregate functions and grouping by every field that isn't aggregated. Try this query:
SELECT `hotel_name`, MAX( `deal_score` ) AS `max_score` FROM `packages_sorted_YHZ` WHERE `hotel_city` = 'Montego Bay'
GROUP BY `hotel_name`
ORDER BY `max_score` DESC
LIMIT 0,3;
It looks like you are facing some very MySql specific issue. In theory, your second query is not valid and should return an error. But MySQL allows for selection of so called hidden columns - the columns that are not mentioned in a group by clause and not aggregated.
As stated in manual, hidden columns values are indeterminate, but in practice it usually picks up the first row walking the index used, regardless of sorting specified by ORDER BY, as sorting is performed after the grouping.
This is vendor-specific issue, so your second query should always fail if used to query other RDBMS. The correct implementation should be something like
SELECT max(`deal_score`) as maxdeal, `hotel_name` FROM `packages_sorted_YHZ` WHERE `hotel_city` = 'Montego Bay'
GROUP BY `hotel_name`
ORDER BY maxdeal
LIMIT 0,3;
You should not use GROUP BY but instead DISTINCT since you want a unique hotel_name.
example:
SELECT DISTINCT hotel_name -- add other fields here
FROM `packages_sorted_YHZ`
WHERE `hotel_city` = 'Montego Bay'
ORDER BY `deal_score` DESC
LIMIT 0,3;
SELECT max(deal_score) as maxdealscore, `hotel_name` * FROM `packages_sorted_YHZ` WHERE `hotel_city` = 'Montego Bay'
GROUP BY `hotel_name`
ORDER BY `deal_score` DESC
LIMIT 0,3;
I have 10k forum topics. I run this query:
SELECT *
FROM `topics`
WHERE category_id = '2'
ORDER BY `last_message` DESC
LIMIT 2990, 10
This checks all rows! All rows! Even after adding index to last_message. last_message is a time() and I want to order all messages by that descending. So, what do you suggest me? Without BETWEEN, because it can't be done with that, unfortunately.
Since you have a filtering condition on category_id, an index on last_message most probably won't help you much.
The query will have to traverse the index and filter the records for category_id = 2. Since traversing an index is more expensive than scanning the table, a filesort can be a more efficient solution, and MySQL may prefer it over the index scan (that's most probably is what is happening in your case).
Also, as #OMG Ponies pointed out, MySQL is not capable of doing late row lookups.
Assuming that your PRIMARY KEY column is called id, you need to create an index on (category_id, last_message, id) and rewrite your query as follows:
SELECT t.*
FROM (
SELECT id
FROM topics
WHERE category_id = 2
ORDER BY
category_id DESC, last_message DESC, id DESC
LIMIT 2990, 10
) q
JOIN topics t
ON t.id = q.id
To get MySQL to use late row lookups, use:
SELECT t.*
FROM TOPICS t
JOIN (SELECT *
FROM `topics`
WHERE category_id = '2'
ORDER BY `last_message` DESC
LIMIT 2990, 10) x ON x.topic_id = t.topic_id
ORDER BY t.topic_id
Without TOPICS column details, I have to assume there is an id column that is auto_increment for the table...
You can read more about the behavior in this article.