【问题标题】:MySQL: Join two tables, select one row at randomMySQL:连接两张表,随机选择一行
【发布时间】:2011-04-21 22:28:59
【问题描述】:

首先,我创建了一个屏幕截图,以解释我拥有什么以及我正在尝试创建什么。更容易理解。

请在此处查看屏幕截图: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/>';
}

?>

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

【问题讨论】:

    标签: php mysql select join


    【解决方案1】:

    我不知道它的性能如何,或者即使它会起作用,但看起来你可以加入一个子查询并通过 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
    

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

    【讨论】:

      【解决方案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 没有意义。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-08-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多