[英]extracting and counting unique columns from an SQL query with multiple joins
我正在尝试找出如何从具有多个联接的SQL查询的结果中的一个给定列中选择X个唯一值,这会产生一些重复,一旦X个唯一值具有被发现。
一个简单的示例可能是一个结果,其中包含用户ID与他们访问过的国家/地区名称之间的一对多关系。
因此,要获得10个人,可能需要40、60或6000行结果,但是10是查询中的必需参数,而返回的实际行数就是达到该数目的唯一人员所需要的。
如果不是太多信息,我想我会参考我真正的PHP / MYSQL示例。
在此示例中,我要从一次查询中选择10个USER_ID,以找到最匹配他们的用户,这些用户是他们到给定点的距离,然后是他们演奏的乐器的权重,然后是他们演奏的任何样式的权重。 (样式和乐器的权重表示每个成员的兴趣或技能水平,其中1是他们的最爱或最好)。
因为样式和乐器的权重是结果顺序不可或缺的部分,所以我认为我需要使用多个联接运行一个biq查询,以使所有内容均按正确的优先顺序排列。 ),这与仅按距离搜索然后循环遍历这些结果相反,在另一个查询中查找了将乐器和样式信息结合在一起的条件。
一些相关的表及其列。
成员:
USER_ID
PASSWORD
FIRST_NAME
LAST_NAME
BIO
BIO_IMAGE
WILL_CONNECT_STATUS
PROFILE_COMPLETE
EMAIL
SIGNUP_DATE
LAST_LOGIN
ACCOUNT_TYPE
EMAIL_ACTIVATED
NOTIFY_MSG int(11)
NOTIFY_CONN_REQ
NOTIFY_PROF_CHANGE
LATITUDE
LONGTITUDE
Members_inst:
ID
USER_ID
INSTRUMENT_ID
ACTIVE
WEIGHT
仪器:
id
name
active
Members_styles:
ID
USER_ID
STYLE_ID
ACTIVE
WEIGHT
样式:
id
style
active
到目前为止,这是一个测试查询。 似乎给了我一个层叠的一对多结果集,所有内容都以正确的顺序排列。 我知道我的LIMIT参数不能满足我的需求,但是我想将结果范围从返回的原始行数转换为m.USER_ID列中的唯一值数。 我只需要能够在“一对多”中选择一个“范围”即可,例如1-10、11-20等。 我想寻找某种循环来检测m.USER_ID的新值,以此作为检测所需范围的开始和结束的手段。
SELECT
m.USER_ID,
m.FIRST_NAME,
m.LAST_NAME,
m.LATITUDE,
m.LONGTITUDE,
mi.INSTRUMENT_ID,
i.name,
mi.WEIGHT AS MI_WEIGHT,
ms.STYLE_ID,
s.style, ms.WEIGHT AS MS_WEIGHT,( 6371 * acos( cos( radians(-38.14854370) ) * cos( radians( LATITUDE ) ) * cos( radians( LONGTITUDE ) - radians(144.36134790) ) + sin( radians(-38.14854370) ) * sin( radians( LATITUDE ) ) ) )
AS distance
FROM members m
INNER JOIN members_inst mi
ON m.USER_ID = mi.USER_ID
INNER JOIN instruments i
ON mi.INSTRUMENT_ID = i.id
INNER JOIN members_styles ms
ON m.USER_ID = ms.USER_ID
INNER JOIN styles s
ON ms.STYLE_ID = s.id
WHERE mi.ACTIVE=1 AND i.active=1 AND mi.WEIGHT != -1 AND ms.WEIGHT!=-1
HAVING distance < 1000 AND USER_ID!= 1 ORDER BY distance, MI_WEIGHT, MS_WEIGHT LIMIT 0 , 10
首先,您需要子查询来找到最适合每个用户的乐器和样式。 对于仪器:
SELECT mi.USER_id,max(i.weight) as max_i_weight
FROM members_inst mi INNER JOIN instruments i ON mi.INSTRUMENT_ID = i.id
WHERE i.weight!=-1 and mi.ACTIVE=1 and i.active=1
GROUP BY mi.USER_ID
和样式:
SELECT ms.USER_id,max(s.weight) as max_s_weight
FROM members_style ms INNER JOIN styles s ON ms.STYLE_ID = s.id
WHERE s.weight!=-1
GROUP BY ms.USER_ID
这些查询对于以后根据乐器和样式的最大权重对用户进行分类很有用。
然后,连接不同的表以构建信息,并按照距离,最大乐器重量和最大样式重量(从上述查询中得知)对用户进行排序。
SELECT
m.USER_ID,
m.FIRST_NAME,
m.LAST_NAME,
m.LATITUDE,
m.LONGTITUDE,
mi.INSTRUMENT_ID,
i.name,
max_i_weight,
ms.STYLE_ID,
s.style,
max_s_weight,
6371 * acos( cos( radians(-38.14854370) ) * cos( radians( LATITUDE ) ) * cos( radians( LONGTITUDE ) - radians(144.36134790) ) + sin( radians(-38.14854370) ) * sin( radians( LATITUDE ) ) ) AS distance
FROM members m INNER JOIN members_inst mi ON m.USER_ID = mi.USER_ID
INNER JOIN (SELECT mi.USER_ID,max(i.weight) as max_i_weight
FROM members_inst mi INNER JOIN instruments i ON mi.INSTRUMENT_ID = i.id
WHERE i.weight!=-1 and mi.ACTIVE=1 and i.active=1
GROUP BY mi.USER_ID) best_instrument ON m.USER_ID=best_instrument.USER_ID
INNER JOIN instruments i ON mi.INSTRUMENT_ID = i.id AND best_instrument.max_i_weight=i.weight
INNER JOIN members_styles ms ON m.USER_ID = ms.USER_ID
INNER JOIN (SELECT ms.USER_id,max(s.weight) as max_s_weight
FROM members_style ms INNER JOIN styles s ON ms.STYLE_ID = s.id
WHERE s.weight!=-1
GROUP BY ms.USER_ID) best_style ON m.USER_ID=best_style.USER_ID
INNER JOIN styles s ON ms.STYLE_ID = s.id AND best_style.max_s_weight=s.weight
WHERE USER_ID!= 1
GROUP BY m.USER_ID
HAVING distance < 1000
ORDER BY distance, max_i_weight, max_s_weight
LIMIT 0 , 10;
结果应该是通过增加距离,然后增加乐器的重量,然后增加样式的重量来列出十个第一用户的列表(没有重复)。 我没有尝试,但是应该可以工作,除了一些错别字...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.