MySQL:分组依据和最接近的整数

时间:2016-07-28 09:56:00

标签: mysql

我有下表

位置:

userId |  zip  | 
----------------
   1   | 12383 |
   1   | 10253 |
   2   | 10523 |
   2   | 14856 |
   2   | 10251 |
   3   |  NULL |    

对于给定的整数X,我想根据谁具有最接近X的列zip中的整数以及相应的zip数来对用户进行排序。如果用户在字段NULL中具有值zip,那么他应该在结尾显示。

实施例:  对于X = 5000,我想得到输出

userId |  zip  | 
----------------
   2   | 10251 |
   1   | 10253 |
   3   |  NULL | 

我设法将userId正确排序为:

SELECT userId, MIN(ABS(3-zip)) as dist FROM location GROUP BY userId Order by -dist DESC

制作表格

userId |  dist  | 
-----------------
   2   |  5251  |
   1   |  5253  |
   3   |  NULL  | 

但我怎样才能获得最近的邮政编码?

2 个答案:

答案 0 :(得分:1)

试试这个:

SELECT userId, ABS(MIN(ABS(zip-3)) + IF(zip - 3 >= 0, 3, -3)) as dist
FROM location
GROUP BY userId
Order by ABS(MIN(ABS(zip-3)) + IF(zip - 3 >= 0, 3, -3)) IS NOT NULL DESC, userId DESC

Demo Here

<强> 编辑:

SELECT userId, SUBSTRING_INDEX(GROUP_CONCAT(zip ORDER BY ABS(zip - 3)), ',', 1) as dist
FROM location
GROUP BY userId
Order by SUBSTRING_INDEX(GROUP_CONCAT(zip ORDER BY ABS(zip - 3)), ',', 1) IS NOT NULL DESC, userId DESC

New solution demo

答案 1 :(得分:1)

SELECT t1.userId,
       t1.zip
FROM location t1
INNER JOIN
(
    SELECT userId, MIN(ABS(3-zip)) AS dist
    FROM location
    GROUP BY userId
) t2
    ON t1.userId = t2.userId AND
       (ABS(3 - t1.zip) = t2.dist OR t2.dist IS NULL)   -- pay careful attention here
ORDER BY -t2.dist DESC                                  -- join on the absolute difference

在这里演示:

SQLFiddle

此查询中有一些技巧:

  • 加入ABS(# - zip)可确保我们选择最接近的拉链,无论其是高还是低
  • 联接中的t2.dist IS NULL条件包括拥有NULL邮政编码的用户
  • 使用ORDER BY -t2.dist DESC升序顺序对邮政编码进行排序,同时将NULL放在结果集的结尾