mysql。随机订购位置并加入列表

发布于 2024-09-24 21:38:59 字数 1586 浏览 2 评论 0原文

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

地点
id 标题 地址 纬度 经度

列表
id location info status

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;

I have two tables: locations and listings.

locations
id title address latitude longitude

listings
id location info status

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

This will list the locations in order by location with the users provided latitude and longitude. Works perfect, but what I really want to do is..

  1. List one "listings" per location, and have the locations remain in order.
  2. If a location has more then one "listings" have it be completely random.

Would it be better to do this all in one SQL query?
Or populate all the locations that have atleast one "listings", then use another query to select a random "listings" for that location?

UPDATE

Provided create table:

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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

樱花细雨 2024-10-01 21:38:59

如果该位置在“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 TABLES

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语句:

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

To output the locations.title if the location has at least 1 row associated with it in the "listings" table, use:

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

Use:

  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

Using MySQL 5.1.49-community, I've successfully rendered the desired results with the query above.

I'm unable to reproduce the OP's duplicated row using:

CREATE TABLES

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 statements:

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');
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文