MySQL Query with in is too much slow - php

I am using this MySQL query. It takes 6.3 seconds or more time.
SELECT * FROM `wp_wpds_tlds` WHERE 1 AND `id` IN (SELECT p.`tld_id` id FROM `wp_wpds_category_pivot` p, `wp_wpds_categories` c WHERE c.id=p.category_id AND `category` LIKE '%City%') ORDER BY `tld` ASC

You have to remove 1 AND after WHERE:
SELECT * FROM wp_wpds_tlds WHERE id IN (SELECT p.tld_idid FROMwp_wpds_category_pivotp,wp_wpds_categoriesc WHERE c.id=p.category_id ANDcategoryLIKE '%City%') ORDER BYtld` ASC

Related

How to get last row of repeating column in php mysql

I have a table as follow. I want to run a query to select the data from the table using php in which if date column is repeated then I want to take only last row of that date
id Date start end publish
1 04-Nov-2015 1000 1300 0
4 04-Nov-2015 2100 3500 0
5 05-Nov-2015 1500 3000 0
like for the below table, When I run the query then the result should come:
4 04-Nov-2015 2100 3500 0
5 05-Nov-2015 1500 3000 0
When I run the query
$select = mysql_query("select * from `entry` Group by `date`") or die(mysql_error());
Then It shows the first row of repeating table, What should I modify in the query that the result should show the last row of repeating colum
Select * from (Select * from entry order by date,id desc) x group by x.date
You can do this with this approach:
$select = mysql_query("select * from `entry` Group by `date`" ORDER BY id DESC LIMIT 1) or die(mysql_error());
Try inner query, I'm not sure following will work exactly as I cant test that now, but for getting result you have to use inner query. Inner query help me to get expected result in my case.
SELECT *
FROM entry p
WHERE id =
(SELECT max(id) FROM entry p2
WHERE p2.id = p.id)
GROUP BY p.date
ORDER BY p.id DESC;
This query will work for you:
create TABLE test (id INT PRIMARY KEY, tdate DATE, start INT);
SELECT t1.* FROM test as t1
LEFT JOIN test as t2
ON (t1.tdate = t2.tdate AND t1.id < t2.id)
WHERE t2.id IS NULL;
Try this query :-
select * from( select * from entry order by id DESC ) new Group by date

MySQL Rand() not in subquery?

I have a set of tracks that need to be played,
There are something like 70 tracks in the database, and my script need to generate a new ID to play in order to start the next track.
Current query: ($row['v_artist'] is the current artist playing)
SELECT *
FROM t_tracks
WHERE v_artist NOT LIKE '%".$row['v_artist']."%'
ORDER BY RAND()
LIMIT 1;
Now I wish to add a subquery to rand() so that it picks a random id, but not from the first 50 (NOT IN?)
Subquery:
SELECT *
FROM `t_playlist`
ORDER BY pl_last_played DESC
LIMIT 50, 1
How can I get a random ID from t_tracks that does not exist in the query for t_playlist?
Conceptually, I think you want this:
SELECT *
FROM t_tracks
WHERE v_artist NOT LIKE '%".$row['v_artist']."%' AND
track_id NOT IN (SELECT track_id FROM t_playlist ORDER BY pl_last_played DESC LIMIT 50)
ORDER BY RAND()
LIMIT 1;
However, MySQL doesn't permit LIMIT in some subqueries, so use LEFT JOIN instead:
SELECT t.*
FROM t_tracks t LEFT JOIN
(SELECT track_id
FROM t_playlist
ORDER BY pl_last_played DESC
LIMIT 50
) p
ON t.track_id = p.track_id
WHERE t.v_artist NOT LIKE '%".$row['v_artist']."%' AND
p.track_id IS NULL
ORDER BY RAND()
LIMIT 1;

Union select with variable, in PHP with PDO. How to do it right?

I am trying to run a query that returns a random row, and 2 rows surrounding that row (previous and next).
I have saved the random result value in a variable so it can be used by all the following queries.
My query is as follows:
SET #rand := (SELECT CEIL(RAND() * MAX(id)) FROM data);
(SELECT * FROM `data` where `id` < #rand AND safe = 1 ORDER BY ID DESC LIMIT 1) UNION
(SELECT * FROM `data` where `id` = #rand AND safe = 1 ORDER BY ID DESC LIMIT 1) UNION
(SELECT * FROM `data` where `id` > #rand AND safe = 1 ORDER BY ID ASC LIMIT 1);
the #rand does contain a valid random ID.
It turns out to have been a display issue on the phpmyadmin interface I had been using from a university pc.
The query executes correctly and in the mysql command line interface the rows are shown correctly. However in PHP/pdo it now returns
PDOStatement::fetchAll(): SQLSTATE[HY000]: General error
whereas the same code without #rand in the query and using a static id for testing purposes, it returns the 3 rows as expected.
I suspect that PDO is having trouble running two SQL statements. I would create a stored procedure to run the statements and use PDO to call the stored proc:
CREATE PROCEDURE spGetThreeRandomRows()
BEGIN
#rand := (SELECT CEIL(RAND() * MAX(id)) FROM data);
(SELECT * FROM `data` where `id` < #rand AND safe = 1 ORDER BY ID DESC LIMIT 1) UNION
(SELECT * FROM `data` where `id` = #rand AND safe = 1 ORDER BY ID DESC LIMIT 1) UNION
(SELECT * FROM `data` where `id` > #rand AND safe = 1 ORDER BY ID ASC LIMIT 1);
END;
Then call it like this:
$stmt = $dbh->prepare("CALL spGetThreeRandomRows()");
$stmt->execute();
You have set that query such that it will return at max 3 rows as you have used LIMIT 1 for each 3 queries.
The other thing, despite this, you have also applied filtering to these query using
where id > #rand
So, how can you expect more than 3 rows ?
May be to get previous & next row, you can use this logic as,
SELECT * FROM `data` where `id` < #rand ORDER BY ID DESC LIMIT 1
UNION
SELECT * FROM `data` where `id` = #rand LIMIT 1
UNION
SELECT * FROM `data` where `id` > #rand ORDER BY ID ASC LIMIT 1
Will work little bit better.
You can get your result by this way
SELECT *
FROM `data`
where `id` between #rand-1 and #rand+
Ok. Then you can try this
SET #rand := (SELECT CEIL(RAND() * MAX(id)) FROM data);
SELECT top 1 * FROM `data` where `id` < #rand AND safe = 1 ORDER BY ID DESC
UNION
SELECT top 1 * FROM `data` where `id` = #rand AND safe = 1
UNION
SELECT top 1 * FROM `data` where `id` > #rand AND safe = 1 ORDER BY ID ASC

Not In mysql subquery Limit

Does anybody have any ideas how I can get around a #1235 - This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery' error?
My query is below ( I've read that I can upgrade mysql but this isn't possible):
$query = #mysql_query("SELECT * FROM posts
WHERE postid NOT IN
( SELECT postid FROM log
ORDER BY posted DESC
LIMIT 10)
ORDER BY (RAND() * Multiplier)
LIMIT 1");
According to this bug, you can use this ugly workaround:
SELECT * FROM t1 WHERE s1 NOT IN
(SELECT * FROM (SELECT s2 FROM t2 ORDER BY s1 LIMIT 1) AS alias)
You can rewrite your query using JOIN:
SELECT *
FROM posts NATURAL LEFT JOIN (
SELECT postid FROM log ORDER BY posted DESC LIMIT 10
) t
WHERE t.postid IS NULL
ORDER BY RAND()
LIMIT 1
Be aware, however, that ORDER BY RAND() is very expensive. Not only must a random value be calculated for each record, but then a sort must be performed on the results. Indexes are of no use.
You would fare better if you had a column col containing unique integers, then with an index on col you can very rapidly obtain a random record with:
SELECT *
FROM posts NATURAL LEFT JOIN (
SELECT postid FROM log ORDER BY posted DESC LIMIT 10
) t JOIN (
SELECT RAND() * MAX(col) AS rand FROM posts
) r ON posts.col >= r.rand
WHERE t.postid IS NULL
LIMIT 1
Note that the uniformity of such "randomness" will depend on the distribution of the integers within col after any other filtering has taken place.

Limit the amount of results from mySQL conditionally?

Here is my query:
SELECT * FROM Photos WHERE Event_ID IN ($eventidstring)
I know I can limit the total amount of results from this query using LIMIT 5
I need the Limit the amount of results Per value in $eventidstring.
So if $eventidstring = 23,41,23*
*And there are 10 results WHERE Event_ID = 23, I want to limit this amount to 5. The same for all the other values in $eventidstring.
You may have some joy doing something similar to Oracle's RANK by PARITION in MySQL.
Sadly this feature is not available in MySQL though you can work around it using this method
Dump that in an inline view and then select those rows with rank <= 5;
Hence:
SELECT t.* FROM (
SELECT (
CASE Event_id
WHEN #curEventId
THEN #curRow := #curRow + 1
ELSE #curRow := 1 AND #curEventId := Event_Id END
) AS rank,
p.*
FROM Photos p INNER JOIN (SELECT #curRow := 0, #curEventId := '') r
ORDER BY p.Event_Id DESC
) t
WHERE t.rank <= 5 ORDER BY t.Event_Id asc;
Consider how you are going to 'choose' the top five by Event_Id too. You can always add in more after the ORDER BY p.Event_Id DESC to decide this.
I take it you're writing that query somewhere inside your PHP, so you need to split the $eventidstring into it's component values, form a SELECT for each and UNION all after the first one.
You sould do this with a loop of some sort, and concatenate the query strings in the loop...
If I understand correctly and you want to get five of each, you can use this:
(SELECT * FROM Photos WHERE Event_ID = 23 LIMIT 5)
UNION
(SELECT * FROM Photos WHERE Event_ID = 41 LIMIT 5)
UNION
(SELECT * FROM Photos WHERE Event_ID = ... LIMIT 5)
...
Maybe with a SELECT UNION but you need a new select for each value:
SELECT * FROM Photos WHERE Event_ID = 23 LIMIT 5
UNION SELECT * FROM Photos WHERE Event_ID = 41 LIMIT 5
UNION SELECT ...

Categories