从具有多个连接的SQL查询中提取和计数唯一列

时间:2014-07-29 06:19:42

标签: php mysql sql loops join

我试图找出如何从具有多个连接的SQL查询的结果中的一个给定列中选择X个唯一值,这会产生一些需要在X后重新过滤(后查询)的重复已找到唯一值的数量。

一个简单的例子可能是包含用户ID的一对多关系和他们访问过的国家/地区名称的结果。

因此,可能需要40,60或6000行结果才能获得10个人,但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    

1 个答案:

答案 0 :(得分:0)

首先,你需要子查询来找到每个用户具有最佳权重的乐器和样式。对于乐器:

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;

结果应该是十个第一个用户的列表(没有任何重复),通过增加距离,然后增加仪器重量,然后增加样式重量。 我不尝试,但它应该工作,除了一些错别字......