我有此表的列结构:
id - n1 - n2 - n3
这里是一些伪数据:
id - n1 - n2 - n3
1 - 3 - 2 - 1
2 - 6 - 5 - 7
3 - 2 - 3 - 1
4 - 1 - 6 - 5
5 - 5 - 6 - 7
6 - 3 - 5 - 6
我们的想法是依次选择和计数n1,n2和n3的每个唯一不同的组。
例如,我们可以得到以下结果:
total - n1s - n2s - n3s
2 - 1 - 2 - 3
2 - 5 - 6 - 7
1 - 1 - 5 - 6
1 - 3 - 5 - 6
您能帮我设置实现该目标的状态吗?
我正在尝试不进行多重选择和PHP数组排序...
谢谢。
答案 0 :(得分:0)
请考虑以下内容-标准化数据集...
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id INT NOT NULL
,n INT NOT NULL
,val INT NOT NULL
,PRIMARY KEY(id,n)
);
INSERT INTO my_table VALUES
(1, 1, 3),
(1, 2, 2),
(1, 3, 1),
(2, 1, 6),
(2, 2, 5),
(2, 3, 7),
(3, 1, 2),
(3, 2, 3),
(3, 3, 1),
(4, 1, 1),
(4, 2, 6),
(4, 3, 5),
(5, 1, 5),
(5, 2, 6),
(5, 3, 7),
(6, 1, 3),
(6, 2, 5),
(6, 3, 6);
这是一个快速的(写的)肮脏的解决方案。可以提供更快/更优雅的解决方案...
SELECT vals
, COUNT(*) total
FROM
( SELECT id
, GROUP_CONCAT(val ORDER BY val) vals
FROM my_table
GROUP
BY id
) x
GROUP
BY vals;
+-------+-------+
| vals | total |
+-------+-------+
| 1,2,3 | 2 |
| 1,5,6 | 1 |
| 3,5,6 | 1 |
| 5,6,7 | 2 |
+-------+-------+
答案 1 :(得分:0)
我们只需要表达式即可对n1,n2和n3列中的值进行“排序”。如果有,那么我们可以做一个简单的GROUP BY
和COUNT
。
SELECT COUNT(1) AS total
, IF(t.n1<=t.n2,IF(t.n1<=t.n3,t.n1,t.n3),IF(t.n2<=t.n3,t.n2,t.n3)) AS n1s
, IF(t.n1<=t.n2,IF(t.n2<=t.n3,t.n2,IF(t.n1<=t.n3,t.n3,t.n1)),IF(t.n1<=t.n3,t.n1,IF(t.n2<=t.n3,t.n3,t.n2 ))) AS n2s
, IF(t.n1<=t.n2,IF(t.n2<=t.n3,t.n3,t.n2),IF(t.n1<=t.n3,t.n3,t.n1)) AS n3s
FROM this_table_column_structure t
GROUP BY n1s,n2s,n3s
ORDER BY total DESC, n1s, n2s, n3s
将返回
total n1s n2s n3s
----- ---- ---- ----
2 1 2 3
2 5 6 7
1 1 5 6
1 3 5 6
答案 2 :(得分:0)
作为第一种方法(如果时间允许),您应该按照@Strawberry的normalizing
的建议,考虑answer您的表但是,第二种方法可以利用User Defined Functions来允许任意数量的列(尽管由于字符串操作和冒泡排序而效率低下)。
我们基本上需要创建一个函数,该函数可以对逗号分隔的字符串中的值进行排序。我找到了一个可以进行排序的工作功能。从here复制代码:
-- sort comma separated substrings with unoptimized bubble sort
DROP FUNCTION IF EXISTS sortString;
DELIMITER |
CREATE FUNCTION sortString(inString TEXT) RETURNS TEXT
BEGIN
DECLARE delim CHAR(1) DEFAULT ','; -- delimiter
DECLARE strings INT DEFAULT 0; -- number of substrings
DECLARE forward INT DEFAULT 1; -- index for traverse forward thru substrings
DECLARE backward INT; -- index for traverse backward thru substrings, position in calc. substrings
DECLARE remain TEXT; -- work area for calc. no of substrings
-- swap areas TEXT for string compare, INT for numeric compare
DECLARE swap1 TEXT; -- left substring to swap
DECLARE swap2 TEXT; -- right substring to swap
SET remain = inString;
SET backward = LOCATE(delim, remain);
WHILE backward != 0 DO
SET strings = strings + 1;
SET backward = LOCATE(delim, remain);
SET remain = SUBSTRING(remain, backward+1);
END WHILE;
IF strings < 2 THEN RETURN inString; END IF;
REPEAT
SET backward = strings;
REPEAT
SET swap1 = SUBSTRING_INDEX(SUBSTRING_INDEX(inString,delim,backward-1),delim,-1);
SET swap2 = SUBSTRING_INDEX(SUBSTRING_INDEX(inString,delim,backward),delim,-1);
IF swap1 > swap2 THEN
SET inString = TRIM(BOTH delim FROM CONCAT_WS(delim
,SUBSTRING_INDEX(inString,delim,backward-2)
,swap2,swap1
,SUBSTRING_INDEX(inString,delim,(backward-strings))));
END IF;
SET backward = backward - 1;
UNTIL backward < 2 END REPEAT;
SET forward = forward +1;
UNTIL forward + 1 > strings
END REPEAT;
RETURN inString;
END |
DELIMITER ;
您将需要在MySQL服务器上运行此代码,以便该函数在查询中可用,就像本机内置的MySQL函数一样。现在,查询部分变得简单。您需要做的就是用逗号Concat_ws()
的所有数字列。然后,对串联的字符串应用sortString()
函数。最终,使用Group By
子句中的“有序”字符串来获得所需的结果。
尝试:
SELECT sortString(CONCAT_WS(',', n1, n2, n3)) AS n_sequence -- add more columns here
COUNT(id) AS total
FROM your_table
GROUP BY n_sequence
ORDER BY total DESC
现在,我建议您可以使用应用程序代码将以逗号分隔的n_sequence
更改回表格列显示。