为什么RAND()搞乱了SQL子查询?

时间:2016-10-22 00:16:58

标签: mysql sql

我的目标是选择随机业务,然后选择该业务' id得到他们所有的广告。我的查询得到了意想不到的结果。返回的广告行数始终是我假设的值" SELECT id FROM Business ORDER BY RAND()LIMIT 1"。我有3个企业,只有1个企业有广告行(其中5个)但它总是显示在同一企业的5个广告中的1-3个之间。

SELECT * FROM Advertisement WHERE business_id=(SELECT id FROM Business ORDER BY RAND() LIMIT 1) ORDER BY priority

业务表: Business TABLE

广告表: Advertisement TABLE

广告和商家数据表:

INSERT INTO `Advertisement` (`id`, `business_id`, `image_url`, `link_url`, `priority`) VALUES
(1, 1, 'http://i64.tinypic.com/2w4ehqw.png', 'https://www.dennys.com/food/burgers-sandwiches/spicy-sriracha-burger/', 1),
(2, 1, 'http://i65.tinypic.com/zuk1w1.png', 'https://www.dennys.com/food/burgers-sandwiches/prime-rib-philly-melt/', 2),
(3, 1, 'http://i64.tinypic.com/8yul3t.png', 'https://www.dennys.com/food/burgers-sandwiches/cali-club-sandwich/', 3),
(4, 1, 'http://i64.tinypic.com/o8fj9e.png', 'https://www.dennys.com/food/burgers-sandwiches/bacon-slamburger/', 4),
(5, 1, 'http://i68.tinypic.com/mwyuiv.png', 'https://www.dennys.com/food/burgers-sandwiches/the-superbird/', 5);

INSERT INTO `Business` (`id`, `name`) VALUES
(1, 'Test Dennys'),
(2, 'Test Business 2'),
(3, 'Test Business 3');

3 个答案:

答案 0 :(得分:3)

您假设您的查询执行了它无法执行的操作。

(SELECT id FROM Business ORDER BY RAND() LIMIT 1)在查询开始时未实现。它为每一行评估了 ...因此,对于每一行,我们都要测试该business_id是否与新执行的子查询实例的结果相匹配。更全面的测试数据(包括多个业务)应该揭示这一点。

您需要将结果具体化为派生表,然后加入它。

SELECT a.* 
  FROM Advertisement a
  JOIN (
        SELECT (SELECT id 
                  FROM Business 
                 ORDER BY RAND() 
                 LIMIT 1) AS business_id
        ) b ON b.business_id = a.business_id;

( SELECT ... ) x构造创建一个临时表,该表仅在查询期间存在并使用别名x。这些表可以像真实表一样加入。

MySQL称之为Subquery in the FROM Clause

答案 1 :(得分:0)

尝试以下查询

SELECT * FROM Advertisement WHERE business_id = (select floor(1 + rand()* (select count(*) from Business)));

答案 2 :(得分:0)

要以随机顺序检索行,请使用SELECT *而不是Id,然后查询其ID。

SELECT * FROM Advertisement WHERE business_id=(SELECT ID FROM (SELECT * FROM Business ORDER BY RAND() LIMIT 1) as table1)

在这种情况下,您的示例数据仅在rand返回1时才会得到结果。