2013-10-08 58 views
-1

我有一个表格,其中包含按照特定顺序一起预订的项目。这会产生一个带有这样的数据集的表。识别表格中的排序顺序

id item_id group_id 
1  1  1 
2  2  1 
3  3  1 
4  1  2 
5  2  2 
6  3  2 
7  2  3 
8  1  3 
9  3  3 
10  3  4 
11  2  4 
12  1  4 
13  1  5 
14  2  5 
15  3  5 
16  4  5 
. 
. 
. 

现在,我找的是那个发现组内的不同的排序顺序,并且可以指示占主导地位的一个查询(或多个)。在这种情况下,答案应该是这样的:

group_id order_used_nr_times 
    1  3 
    2  3 
    3  1 
    4  1 
    5  3 
    .    
    .    
    .    

注意,作为第5组表示,这是非常有可能的是,组内有更多的项目和搜索的项目是一个子集(例如,寻找订单项目4,5,6和发现在1,2,3,4,5,6,7,8,9是一个选项。

我一直在考虑一个查询与组和具有或与MySQL的东西转,但我不能让我的头周围

附加信息:

我需要查询给我的主导排序顺序(这种情况下1,2,3),所以它可以用于插入一个新的组,其中包括1,2,3订购1,2,3而不是2,1,33,2,1,在此示例中的项目。

从业务角度来看:有两个“人员组”使用系统,A组和B组.A组知道如何订购物料,因此手动设置订单,系统只是将数据插入给定的顺序。 B组,但不知道顺序。因此,系统(查询)需要查看A组是否已经预订了这些项目,如果是这样,它们以哪种顺序最经常发生(顺序可以如示例所示那样不同)。然后将来自组A的顺序用于插入来自组B的数据,假设这是最合理的。

我希望这个解释有帮助。

+0

我想用变量将是解决http://dev.mysql.com/doc/refman/5.0/en/user-variables.html – biziclop

+0

除非我误解,一个简单的GROUP BY应该足够了:'SELECT COUNT (*),group_id FROM MyTable GROUP BY COUNT(*)' – cbeckner

+3

您可以扩展一些关于如何从示例数据获得预期输出的信息吗?一直盯着这几分钟,现在仍然没有得到你想要的...... –

回答

1

可以找到相同组的计数。你可以第一组的行通过group_id和GROUP_CONCAT的item_id值:

SELECT 
    group_id, 
    GROUP_CONCAT(item_id ORDER BY id) AS item_list 
FROM atable 
GROUP BY 
    group_id 
; 

这会给你一个结果集是这样的:

group_id item_list 
-------- --------- 
1   1,2,3 
2   1,2,3 
3   2,1,3 
4   3,2,1 
5   1,2,3,4 

现在是容易得到的条目数为每不同的项目清单:

SELECT 
    item_list, 
    COUNT(*) AS nr_times 
FROM (
    SELECT 
    group_id, 
    GROUP_CONCAT(item_id ORDER BY id) AS item_list 
    FROM atable 
    GROUP BY 
    group_id 
) AS s 
GROUP BY 
    item_list 
; 

并且查询返回:

item_list nr_times 
--------- -------- 
1,2,3  2 
1,2,3,4 1 
2,1,3  1 
3,2,1  1 

这不是您之后的输出,因为您需要组ID旁边的计数。因此,需要被连接到前行集中的最后一行设置:

SELECT 
    groups.group_id, 
    counts.nr_times 
FROM (
    SELECT 
    group_id, 
    GROUP_CONCAT(item_id ORDER BY id) AS item_list 
    FROM atable 
    GROUP BY group_id 
) AS groups 
INNER JOIN (
    SELECT 
    item_list, 
    COUNT(*) AS nr_times 
    FROM (
    SELECT GROUP_CONCAT(item_id ORDER BY id) AS item_list 
    FROM atable 
    GROUP BY group_id 
) AS s 
    GROUP BY item_list 
) AS counts 
ON groups.item_list = counts.item_list 
; 

输出:

group_id nr_times 
-------- -------- 
1   2 
2   2 
3   1 
4   1 
5   1 

在这一点上,很明显,分组同一组两次可能不是一个非常好的主意。也许这将是更好的第一分组的结果存储到一个临时表,然后用它来得到最终结果:

CREATE TEMPORARY TABLE temp_results 
AS 
SELECT 
    group_id, 
    GROUP_CONCAT(item_id ORDER BY id) AS item_list 
FROM atable 
GROUP BY 
    group_id 
; 

SELECT 
    groups.group_id, 
    counts.nr_times 
FROM temp_results AS groups 
INNER JOIN (
    SELECT 
    item_list, 
    COUNT(*) AS nr_times 
    FROM temp_results 
    GROUP BY item_list 
) AS counts 
ON groups.item_list = counts.item_list 
; 

我们得到的数字,如您所需的输出,你可以尝试匹配两套与LIKE,像这样:

SELECT 
    groups.group_id, 
    counts.nr_times 
FROM temp_results AS groups 
INNER JOIN (
    SELECT 
    item_list, 
    COUNT(*) AS nr_times 
    FROM temp_results 
    GROUP BY item_list 
) AS counts 
ON CONCAT(',', groups.item_list, ',') LIKE CONCAT('%,', counts.item_list, ',%') 
OR CONCAT(',', counts.item_list, ',') LIKE CONCAT('%,', groups.item_list, ',%') 
; 

上述会给你以下几点:

group_id nr_times 
-------- -------- 
1   2 
1   1 
2   2 
2   1 
3   1 
4   1 
5   2 
5   1 

很显然,你现在只需要坚持

GROUP BY groups.group_id 

在最后一个查询的结束,以及

SUM(counts.nr_times) AS order_used_nr_times 

更换counts.nr_times在SELECT子句,以获得相同的输出你的问题:

group_id order_used_nr_times 
-------- ------------------- 
1   3 
2   3 
3   1 
4   1 
5   3 

但是请注意,如果您有包含项目1,2,3,3,4,51,2,3,4,5,6的组,则上次查询中使用的LIKE加入条件将与前两个组中的任意一个匹配只有第三个,而不是彼此,而第三个组将与前两个组匹配。

我不确定这是否符合您的要求,因为我仍然无法在那个特定的问题上作出解释(对不起)。我希望这篇文章至少能给你一些想法,最终如何才能取得正确的结果。

+0

太令人印象深刻!这是一个很好的解释,它是我一直在寻找的东西!我现在对最终结果集进行排序,使用连接的ID并在插入时使用ORDER BY FIELD(item_id,item_list),并以最常见的方式存储ID。非常好,非常感谢你! – jan