我的问题最好用一个简单的例子来解释:你按照身高排列学校的所有孩子。你想打破这条线,这样休息的一边就有十个女孩。你不知道会有多少男孩,因为这取决于他们的身高。
我的表格包含用户名的地理位置,每个用户名可以包含多个位置。我的下面的代码使用自联接查找地理上最接近输入用户名的用户名。通常这样的连接将包括WHERE input_username <> input_username
,但我不这样做,因为我发现将input_username
作为结果集的一部分很有用。但是,我想从输入用户名返回10个结果APART。
如果我理解正确你不能用sql限制子句这样做,因为不允许使用函数,但还有另一种方法吗?
SELECT
t1.`username`,
t2.`title`,
t2.`lat`,
t2.`long`,
DATE_FORMAT(greatest(t1.`from`, t2.`from`), '%d/%m/%Y') `begin`,
DATE_FORMAT(least(t1.`to`, t2.`to`), '%d/%m/%Y') `end`,
CAST((format((POWER(POWER(((t1.`long` - t2.`long`)*1112), 2) + POWER(((t1.`lat` - t2.`lat`)*1112), 2), 0.5)), 2))*0.1 AS DECIMAL(5,3)) distance,
t2.`username`,
IF(t2.`username`=t1.`username`, 'inquirer', 'neighbour') `type`
FROM
entries t1,
entries t2
WHERE
t1.`username` = username AND greatest(t1.`from`, t2.`from`) < least(t1.`to`, t2.`to`)
ORDER BY distance
LIMIT 10;
好的,有没有办法按距离排序但是限制结果集,以便它包含许多需要包含10个'邻居''类型的?
目前,输出限制为10,其中一些将是“查询者”或输入用户名,有些将是“邻居”,或者是用户名,接近用户名进行查询。我想限制结果集,以便输入用户名以外有10个返回。
上面的代码返回如下:
username title lat long begin end distance username type
uv "Title of entry 168" 51.595024 -0.128904 07/04/1919 07/04/1929 0.000 uv inquirer
uv "Title of entry 723" 51.610653 0.028761 26/09/1917 26/09/1927 0.000 uv inquirer
uv "Title of entry 444" 51.613369 0.034306 26/09/1917 21/10/1923 0.687 ee neighbour
uv "Title of entry 565" 51.588711 -0.129161 22/10/1919 07/04/1929 0.703 fh neighbour
uv "Title of entry 364" 51.601067 -0.121640 14/10/1923 07/04/1929 1.051 kg neighbour
uv "Title of entry 157" 51.620327 0.029985 12/12/1926 26/09/1927 1.084 ub neighbour
uv "Title of entry 1625" 51.608444 0.018629 30/08/1926 26/09/1927 1.153 wm neighbour
uv "Title of entry 554" 51.611248 -0.129845 07/04/1919 11/01/1928 1.807 gw neighbour
uv "Title of entry 1087" 51.599979 -0.113263 29/10/1924 07/04/1929 1.824 es neighbour
uv "Title of entry 1223" 51.620193 0.043415 26/09/1917 16/07/1922 1.944 bm neighbour
fancypants提出的代码返回如下:
inusername title lat long begin end distance outusername type my_neighbour_counter
uv "Title of entry 16" 51.649853 -0.012949 05/12/1925 26/09/1927 6.365 sh neighbour 5
uv "Title of entry 31" 51.569290 -0.206963 07/04/1919 02/07/1923 9.140 mj neighbour 10
uv "Title of entry 22" 51.532021 -0.223247 07/01/1925 07/04/1929 12.615 pn neighbour 6
uv "Title of entry 16" 51.649853 -0.012949 05/12/1925 07/04/1929 14.263 sh neighbour 4
uv "Title of entry 10" 51.473103 -0.203539 07/04/1919 21/05/1925 15.896 jx neighbour 2
uv "Title of entry 22" 51.532021 -0.223247 07/01/1925 26/09/1927 29.356 pn neighbour 7
uv "Title of entry 10" 51.473103 -0.203539 26/09/1917 21/05/1925 30.021 jx neighbour 3
uv "Title of entry 28" 51.354542 -0.259209 07/04/1919 31/08/1927 30.415 ui neighbour 8
uv "Title of entry 28" 51.354542 -0.259209 26/09/1917 31/08/1927 42.855 ui neighbour 9
可以看出,这仍然限于10行。我想做的是下面的Strawerberry所做的,除了适用于我的代码。
最终工作的代码如下,然后是结果返回。它可能可以更有效地完成。我要感谢fancyPants和Strawerberry。
SET @x := 'st';
SET @rank=0;
SELECT * FROM (SELECT *, if(inqu = neig, @rank:=@rank, @rank:=@rank + 1) `rank`
FROM (SELECT t1.`username` inqu, t2.`title`, t2.`lat`, t2.`long`,
DATE_FORMAT(greatest(t1.`from`, t2.`from`), '%d/%m/%Y') `begin`,
DATE_FORMAT(least(t1.`to`, t2.`to`), '%d/%m/%Y') `end`,
CAST((format((POWER(POWER(((t1.`long` - t2.`long`) * 1112), 2) +
POWER(((t1.`lat` - t2.`lat`) * 1112), 2), 0.5)), 2)) * 0.1
AS DECIMAL (5 , 3 )) distance,
AS DECIMAL (5 , 3 )) distance,
t2.`username` neig,
IF(t2.`username` = t1.`username`, 'inquirer', 'neighbour') `type`
FROM
entries t1, entries t2
WHERE
t1.`username` = @x
AND greatest(t1.`from`, t2.`from`) < least(t1.`to`, t2.`to`)
ORDER BY distance) m) n WHERE `rank` <= 10;
inqu title lat long begin end distance neig type rank
st "Title of entry 482" 51.511539 -0.034709 20/11/1976 21/11/1986 0.000 st inquirer 0
st "Title of entry 144" 51.523846 -0.188672 17/04/1959 17/04/1969 0.000 st inquirer 0
st "Title of entry 1034" 51.504379 -0.007122 22/02/1901 23/02/1911 0.000 st inquirer 0
st "Title of entry 956" 51.388729 -0.149454 26/09/1954 25/09/1964 0.000 st inquirer 0
st "Title of entry 1432" 51.391411 -0.149341 26/09/1954 08/07/1960 0.298 vg neighbour 1
st "Title of entry 1074" 51.519535 -0.182533 17/04/1959 29/04/1965 0.834 sw neighbour 2
st "Title of entry 742" 51.526321 -0.180818 03/08/1967 17/04/1969 0.916 ig neighbour 3
st "Title of entry 863" 51.519028 -0.179766 17/04/1959 05/04/1966 1.126 ad neighbour 4
st "Title of entry 728" 51.520554 -0.179007 21/10/1960 17/04/1969 1.135 pu neighbour 5
st "Title of entry 597" 51.526016 -0.177974 09/03/1966 17/04/1969 1.214 xj neighbour 6
st "Title of entry 1527" 51.514561 -0.045765 09/07/1986 21/11/1986 1.275 bh neighbour 7
st "Title of entry 892" 51.497967 -0.016889 26/01/1911 23/02/1911 1.299 kv neighbour 8
st "Title of entry 1004" 51.527172 -0.177020 17/04/1959 24/04/1960 1.347 li neighbour 9
st "Title of entry 1325" 51.517700 -0.199251 17/04/1959 11/01/1966 1.360 nj neighbour 10
答案 0 :(得分:0)
理解它就像你想让用户等按距离排序。有多少并不重要,但最多应该有10个邻居,对吗?
SELECT * FROM (
SELECT
t1.`username`,
t2.`title`,
t2.`lat`,
t2.`long`,
DATE_FORMAT(greatest(t1.`from`, t2.`from`), '%d/%m/%Y') `begin`,
DATE_FORMAT(least(t1.`to`, t2.`to`), '%d/%m/%Y') `end`,
CAST((format((POWER(POWER(((t1.`long` - t2.`long`)*1112), 2) + POWER(((t1.`lat` - t2.`lat`)*1112), 2), 0.5)), 2))*0.1 AS DECIMAL(5,3)) distance,
t2.`username`,
IF(t2.`username`=t1.`username`, 'inquirer', 'neighbour') `type`,
@neighbour_counter := IF(t2.`username`=t1.`username`, @neighbour_counter, @neighbour_counter + 1) AS my_neighbour_counter
FROM
entries t1,
entries t2,
(SELECT @neighbour_counter := 1) my_variables
WHERE
t1.`username` = username AND greatest(t1.`from`, t2.`from`) < least(t1.`to`, t2.`to`)
ORDER BY distance
) sq WHERE my_neighbour_counter <= 10
编辑:修正错误,在查询者而不是邻居上增加变量...
答案 1 :(得分:0)
SELECT * FROM children;
+------------+--------+--------+
| name | height | gender |
+------------+--------+--------+
| Adam | 126 | M |
| Alice | 103 | F |
| Ben | 106 | M |
| Bernadette | 133 | F |
| Charlie | 101 | M |
| Claire | 102 | F |
| Dan | 139 | M |
| Donna | 96 | F |
| Edward | 141 | M |
| Erica | 119 | F |
| Fiona | 133 | F |
| Frank | 139 | M |
| George | 122 | M |
| Georgina | 134 | F |
| Harriet | 135 | F |
| Henry | 141 | M |
| Inigo | 139 | M |
| Irene | 96 | F |
| Jessica | 103 | F |
| John | 122 | M |
| Kenneth | 144 | M |
| Kimberley | 132 | F |
| Lee | 103 | M |
| Lorraine | 134 | F |
| Michael | 134 | M |
| Michelle | 102 | F |
+------------+--------+--------+
SET @rank=0;
SELECT name
, height
, gender
FROM
( SELECT *
, CASE WHEN gender = 'f' THEN @rank:=@rank+1 ELSE @rank:=@rank END rank
FROM children
ORDER
BY height
) m
WHERE rank <= 10;
+------------+--------+--------+
| name | height | gender |
+------------+--------+--------+
| Donna | 96 | F |
| Irene | 96 | F |
| Charlie | 101 | M |
| Michelle | 102 | F |
| Claire | 102 | F |
| Lee | 103 | M |
| Alice | 103 | F |
| Jessica | 103 | F |
| Ben | 106 | M |
| Erica | 119 | F |
| John | 122 | M |
| George | 122 | M |
| Adam | 126 | M |
| Kimberley | 132 | F |
| Fiona | 133 | F |
| Bernadette | 133 | F |
+------------+--------+--------+