简体   繁体   English

在带有PDO的PHP中,用变量联合选择。 怎么做对?

[英]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). 我试图运行一个查询,该查询返回一个随机行,以及围绕该行的2行(上一个和下一个)。

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. @rand确实包含有效的随机ID。

It turns out to have been a display issue on the phpmyadmin interface I had been using from a university pc. 原来,这是我在大学电脑上使用的phpmyadmin界面上的显示问题。

The query executes correctly and in the mysql command line interface the rows are shown correctly. 查询正确执行,并且在mysql命令行界面中,行正确显示。 However in PHP/pdo it now returns 但是在PHP / pdo中,它现在返回

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. 而在查询中没有@rand且使用静态ID进行测试的相同代码,它会按预期返回3行。

You have set that query such that it will return at max 3 rows as you have used LIMIT 1 for each 3 queries. 您已经设置了该查询,以使它最多返回3行,因为您对每3个查询使用了LIMIT 1

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 ? 那么,您如何期望超过3行?

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

I suspect that PDO is having trouble running two SQL statements. 我怀疑PDO在运行两个SQL语句时遇到问题。 I would create a stored procedure to run the statements and use PDO to call the stored proc: 我将创建一个存储过程来运行语句并使用PDO调用存储过程:

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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM