【问题标题】:Mysql. Order locations and join listings randomlymysql。随机订购位置并加入列表
【发布时间】:2010-09-25 18:58:19
【问题描述】:

我有两个表:位置和列表。

位置
idtitleaddresslatitudelongitude

列表
idlocationinfostatus

SELECT locations.title, 
       locations.address, 
       ( 3959 * acos( cos( radians('".$center_lat."') ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians('".$center_lng."') ) + sin( radians('".$center_lat."') ) * sin( radians( latitude ) ) ) ) AS distance      
  FROM locations 
ORDER BY distance

这将按位置按用户提供的纬度和经度列出位置。工作完美,但我真正想做的是..

  1. 为每个位置列出一个“列表”,并使位置保持有序。
  2. 如果一个位置有多个“列表”,则它是完全随机的。

在一个 SQL 查询中完成这一切会更好吗? 或者填充至少有一个“列表”的所有位置,然后使用另一个查询为该位置选择一个随机“列表”?

更新

提供创建表:

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

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

【问题讨论】:

    标签: php sql mysql greatest-n-per-group ranking


    【解决方案1】:

    如果位置在“listings”表中至少有 1 行与之关联,则要输出 locations.title,请使用:

    SELECT loc.title
      FROM LOCATIONS loc
     WHERE EXISTS(SELECT NULL
                    FROM LISTING li
                   WHERE li.location = loc.id)
    

    用途:

      SELECT x.title, 
             x.address,
             x.distance,
             x.info,
             x.status
        FROM (SELECT loc.title, 
                     loc.address, 
                     ( 3959 * acos( cos( radians('".$center_lat."') ) * cos( radians( latitude ) ) * cos( radians( longitude ) - radians('".$center_lng."') ) + sin( radians('".$center_lat."') ) * sin( radians( latitude ) ) ) ) AS distance,
                     li.*,
                     CASE 
                       WHEN @location = loc.id THEN @rownum := @rownum + 1
                       ELSE @rownum := 1
                     END AS rank,
                     @location := loc.id
                FROM LOCATIONS loc
           LEFT JOIN LISTINGS li ON li.location = loc.id
                JOIN (SELECT @rownum := 0, @location := -1) r
            ORDER BY loc.id, RAND()) x
       WHERE x.rank = 1
    ORDER BY x.distance
    

    使用 MySQL 5.1.49-community,我已经通过上面的查询成功地呈现了所需的结果。

    我无法使用以下方法重现 OP 的重复行:

    创建表格

    CREATE TABLE `locations` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `title` varchar(45) DEFAULT NULL,
      `address_street` varchar(45) DEFAULT NULL,
      `address_city` varchar(45) DEFAULT NULL,
      `address_state` varchar(45) DEFAULT NULL,
      `address_zip` varchar(45) DEFAULT NULL,
      `latitude` decimal(10,6) DEFAULT NULL,
      `longitude` decimal(10,6) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1$$
    
    CREATE TABLE `listings` (
      `id` int(11) NOT NULL,
      `token` varchar(4) DEFAULT NULL,
      `location` varchar(45) DEFAULT NULL,
      `info` varchar(45) DEFAULT NULL,
      `status` varchar(45) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=latin1$$
    

    插入语句:

    INSERT INTO `locations` 
    VALUES (1,'John\'s Ice Cream','1701 S Martin Luther King Jr Blvd','Lansing','MI','48910','42.714672','-84.567139'),
           (2,'7 Eleven','3500 Okemos Rd','Okemos','MI','48864','42.683331','-84.431709'),
           (3,'Kurt\'s Pizza','213 Ann St.','East Lansing','MI','48823','42.736053','-84.481636'),
           (4,'Walmart','16275 National Pkwy','Lansing','MI','48906','42.780350','-84.637238'),
           (5,'Alex\'s Hot dog Shop','8505 Delta Market Dr','Lansing','MI','48917','42.739830','-84.677330');
    
    INSERT INTO `listings` 
    VALUES (19,'39c4','1','5 gallons for $8','active'),
           (21,'89dF','4','2 mens shirts for $2','active'),
           (22,'67oP','1','Ice cream cones for $1','active'),
           (23,'5tG8','2','Large soft drinks only $0.99!','active');
    

    【讨论】:

    • 看起来不错,但在 '@location := loc.id FROM LOCATIONS loc LEFT JOIN LISTINGS li' 附近出现语法错误,似乎无法理解。
    • @Chad Whitaker:我在“AS rank”之后少了一个逗号,已更正。
    • 它现在可以工作,但是.. 1. 它显示没有“列表”的“位置” 2. 如果一个位置有多个,则该项目似乎不是随机的。
    • @Chad Whitaker:您的原始订单不包括关联的listing,因此LEFT JOIN 会产生相同的结果。如果您不想看到没有至少一条 LISTING 记录的 LOCATION 记录,请将“LEFT JOIN LISTINGS”更改为“JOIN LISTINGS”。
    • @Chad Whitaker:ORDER BY loc.id, RAND() 确保除了LOCATION.id 排序之外,行在 MySQL 允许的范围内是随机的。请记住,两个LISTING 记录的随机排序不会出现那么随机;)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-17
    • 2018-09-21
    • 1970-01-01
    • 1970-01-01
    • 2010-11-21
    • 1970-01-01
    相关资源
    最近更新 更多