MySQL:加入两个表,随机选择一行

时间:2010-10-06 16:13:38

标签: php mysql select join

首先,我创建了一个屏幕投射,以解释我拥有的和我正在尝试创建的内容。更容易理解。

请查看此处投放的屏幕:http://www.youtube.com/v/lZf3S3EGHDw?fs=1&hl=en_US&rel=0&hd=1

表:

CREATE TABLE `locations` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `title` varchar(45) DEFAULT NULL,
  `latitude` decimal(10,6) DEFAULT NULL,
  `longitude` decimal(10,6) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

INSERT INTO `locations` (`id`,`title`,`latitude`,`longitude`)
VALUES
    (1,'Randall Automotive Car Repair',42.729642,-84.515524),
    (2,'Belle Tire',42.662458,-84.538177),
    (3,'Better Buy Muffler & Breaks',42.740845,-84.589541),
    (4,'Kwik Car Wash',42.721221,-84.545926);


CREATE TABLE `listings` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `token` varchar(4) DEFAULT NULL,
  `location` varchar(45) DEFAULT NULL,
  `info` varchar(70) DEFAULT NULL,
  `status` varchar(45) DEFAULT NULL,
  `auto_inactive` varchar(10) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;


INSERT INTO `listings` (`id`,`token`,`location`,`info`,`status`,`auto_inactive`)
VALUES
    (35,'4uaJ','1','All employees are NSA certified.','active','0'),
    (36,'RdcX','1','Family Owned and Operated','active','0'),
    (37,'WuaZ','1','Also repair Small engines','active','0'),
    (38,'2jxD','2','Open on the weekends.','active','0'),
    (39,'Xsu4','2','Two locations in this town.','active','0'),
    (40,'p9cB','2','Advertise on Tiger\'s Baseball','active','0'),
    (41,'mYa3','2','Started right here in Michigan','active','0'),
    (42,'Q8g5','3','Building built in 1997','active','0'),
    (43,'l734','3','Great ratings from BBB','active','0'),
    (44,'7cLY','4','Open in the Winter','active','0'),
    (45,'gtlU','4','Largest car wash in town','active','0'),
    (46,'fEjK','4','Owned and Operated by John Smith','active','1285614174'),
    (47,'dRcu','4','Opened in 1987','inactive','0');



<?php

include_once('include.php'); // Calls the Mysql Database`
ini_set('date.timezone', 'America/Detroit');


$user_latitude = 42.7160084;
$user_longitude = -84.5615018;


$sql =  mysqli_query($mysqli, "SELECT 
                                        loc.id, 
                                        loc.title, 
                                        ( 3959 * acos( cos( radians('".$user_latitude."') ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians('".$user_longitude."') ) + sin( radians('".$user_latitude."') ) * sin( radians( latitude ) ) ) ) AS distance

                                FROM 
                                        locations loc 

                                WHERE EXISTS(SELECT NULL FROM listings li
                                        WHERE li.location = loc.id 
                                        AND li.status = 'active' 
                                        AND (li.auto_inactive > '".time()."' OR li.auto_inactive = '0')) 

                                ORDER BY distance");


while($locations = mysqli_fetch_array($sql)) {

        $listings = mysqli_fetch_array(mysqli_query($mysqli, "SELECT listings.token, listings.info FROM listings WHERE (listings.location = '".$locations['id']."') AND listings.status = 'active' AND (listings.auto_inactive > '".time()."' OR listings.auto_inactive = '0') ORDER BY RAND()"));


        echo '<a href="listing.php?id='.$listings['token'].'"><h2>'.$locations['title'].'</h2></a>';

        echo '<h5>Distance: '.sprintf ('%.2f', $locations['distance']).' mi</h5>';
        echo '<p>'.$listings['info'].'</p>';
        echo '<hr/>';
}

?>

如果您需要澄清任何内容,请告诉我。谢谢!

2 个答案:

答案 0 :(得分:2)

这个有效:

SELECT t1.title, t2.token, t2.info
    FROM
        (SELECT loc.id AS id, loc.title AS title,( 3959 * acos( cos( radians('".$user_latitude."') ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians('".$user_longitude."') ) + sin( radians('".$user_latitude."') ) * sin( radians( latitude ) ) ) ) AS distance
            FROM locations loc
            WHERE EXISTS(SELECT NULL FROM listings li
                    WHERE li.location = loc.id
                        AND li.status = 'active'
                        AND (li.auto_inactive > UNIX_TIMESTAMP() OR li.auto_inactive = '0'))
        ) t1
    JOIN
        (SELECT DISTINCT(listings.location) AS location, listings.token AS token, listings.info AS info
            FROM listings
            WHERE listings.status = 'active'
                AND (listings.auto_inactive > UNIX_TIMESTAMP() OR listings.auto_inactive = '0')
            ORDER BY RAND()
        ) t2
    ON t1.id=t2.location
        GROUP BY t2.location
        ORDER BY t2.location ASC;

我还建议更改listings表以使locationstatusauto_inactive列类型为int - 对它们使用varchar毫无意义。

答案 1 :(得分:0)

我不知道它的效果如何,或者即使它会起作用,但看起来你可以加入子查询并通过rand限制/排序。我发现这个question/answer here是我的基础。尝试这样的事情:

SELECT 
    loc.id, 
    loc.title, 
    ( 3959 * acos( cos( radians('".$user_latitude."') ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians('".$user_longitude."') ) + sin( radians('".$user_latitude."') ) * sin( radians( latitude ) ) ) ) AS distance,
    listings.token,
    listings.info
FROM
    locations loc
JOIN
    (SELECT
             location,
             token,
             info
         FROM listings
         WHERE (listings.location=loc.id)
             AND status = 'active'
             AND (auto_inactive > '".time()."' OR listings.auto_inactive = '0')
         ORDER BY RAND() LIMIT 1) listings
     ON listings.location=loc.id
ORDER BY distance

编辑:此外,如果这确实有效,则联接会将位置限制为仅包含列表的位置,因此您无需检查该位置。