【问题标题】:MySQL Statement that reads data from multiple rows从多行读取数据的 MySQL 语句
【发布时间】:2017-07-06 03:56:49
【问题描述】:

我需要用一个 mySql 语句来做一个复杂的 mySQL 查询,我有一个这样的表,每个用户的数据分布在不同的行中

 ID  USER_ID FIELD_ID  VALUE
 1      1       2        my name is paul smith
 2      1       3        books
 3      1       4        loggedin
 4      1       5        busy
 5      1       6        lat
 6      1       7        lon
 7      2       2        my name is big boy
 8      2       3        pens
 9      2       4        offline
 10     2       5        idle
 11     2       6        lat
 12     2       7        lon

每一行包含同一个user_id的不同数据

 FIELD_ID=2 contains the user name
 FIELD_ID=3 contains what they bought
 FIELD_ID=4 logged in or offline
 FIELD_ID=5 is busy or idle
 FIELD_ID=6 is their latitude
 FIELD_ID=7 is their longitude

我需要一个 MySQL 语句,它会返回所有已登录且状态为空闲且已购买图书且距离例如 5 英里以内的用户。

所以有四件事必须同时为真:

 1. user has to be LOGGED IN
 2. user has to be idle
 3. user has to have bought books
 4. user has to be within 5 miles of the office (located at lat=12.3, lon=13.3)

所以我从这个开始(做了上面四件事中的三件事)

 SELECT distinct a.*
  FROM table a
   inner join table b on a.user_id = b.user_id and b.field_id = 5 and b.value='idle'
   inner join table c on a.user_id = c.user_id and c.field_id = 4 and c.value = 'loggedin'
   where a.field_id=3 and a.value='BOOK'

我是一个 mysql 新手,似乎上面的语句创建了三个虚拟表并将它们组合起来进行查询,所以我想再创建两个虚拟表(一个用于 lat,另一个用于 long),并将其与我现有的mySQL 函数 calcDist(lat1,lon1,lat2,lon2) 计算 2 个 gps 点之间的距离,如下所示:

 SELECT distinct a.* 
  FROM table a
   inner join table b on a.user_id = b.user_id and b.field_id = 5 and b.value='idle'
   inner join table c on a.user_id = c.user_id and c.field_id = 4 and c.value = 'loggedin'
   inner join table d on a.user_id = d.user_id and d.field_id = 6
   inner join table e on a.user_id = e.user_id and e.field_id = 7
   where a.field_id=3 and a.value='BOOK' and calcDist(12.3,13.3,d.value,e.value)<5.0;

我添加了两行(d和e)并修改了最后一行,其余相同。

对不起,我是一个真正的 mysql 新手,似乎无法同时比较不同行的值。

有人知道这是否是正确的方法吗?

谢谢!

【问题讨论】:

    标签: mysql


    【解决方案1】:

    我已经编辑了这个,因为草莓写道,需要一些东西来聚合,这对你的数据不起作用。下面的这个解决方案有效。它与您之前所做的非常相似,只是它包含在子查询中。我已经对此进行了测试并且可以使用

    SELECT * FROM
    (SELECT DISTINCT
    x.USER_ID,
    n.value as name,
    b.VALUE as bought,
    l.VALUE as logged,
    s.VALUE as `status`,
    lt.VALUE as lat,
    ln.VALUE as lon
    
    FROM testing x
    
    LEFT JOIN testing n
    ON x.USER_ID = n.USER_ID and n.FIELD_ID = 2
    
    LEFT JOIN testing b
    ON x.USER_ID = b.USER_ID and b.FIELD_ID = 3
    
    LEFT JOIN testing l
    ON x.USER_ID = l.USER_ID and l.FIELD_ID = 4
    
    LEFT JOIN testing s
    ON x.USER_ID = s.USER_ID and s.FIELD_ID = 5
    
    LEFT JOIN testing lt
    ON x.USER_ID = lt.USER_ID and lt.FIELD_ID = 6
    
    LEFT JOIN testing ln
    ON x.USER_ID = ln.USER_ID and ln.FIELD_ID = 7
    
    )tbl
    
    WHERE tbl.logged = 'loggedin'
    AND tbl.status IN ('idle', 'busy')
    AND tbl.bought = 'books'
    AND calcDist(12.3,13.3, tbl.lat, tbl.lon) > 5
    

    你的 calcDist 函数应该可以做类似的事情

    AND (3959 * acos( cos( radians(12.3) ) 
          * cos( radians(x.LAT) ) 
          * cos( radians(x.LON) - radians(13.3)) + sin(radians(12.3))
          * sin( radians(x.LAT) ))) >= 5 
    

    【讨论】:

    • 哇,太好了!!我不知道可以这样做!非常感谢,我试试!!
    • 在没有任何聚合函数的情况下,GROUP BY 将返回一个不确定的结果,所以要么删除它,要么采用更传统的方法,并在每个 CASE 上包含一个 MAX
    • Starwberry - 感谢您的评论,您是否可以按照您的意思编写 SQL 语句,我还不够先进。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-17
    • 2016-05-05
    • 2020-08-05
    • 1970-01-01
    • 2019-06-26
    • 2023-02-17
    相关资源
    最近更新 更多