计算多列中的匹配项

时间:2019-08-25 16:59:36

标签: mysql

我们有一个包含五列的表。每列(num1num2,... num5)的唯一编号从1到90升序排列。 (因此,最低数字在num1中,最高数字在num5中。用户提示输入五个数字(val1val2,... val5) ,在到达数据库之前,由程序再次以升序排序。

任务是从用户给定的五个数字中计数表中有五个,四个,三个和两个匹配项的记录。

计算五场比赛很容易,因为数字顺序相同,因此我不必处理排列。

SELECT count(*) FROM table
WHERE num1 = val1 AND num2 = val2 AND num3 = val3 AND num4 = val4 AND num5 = val5

问题是,我不知道如何开始计算四,三和两场比赛。 我不知道SQL是否还能够执行这样的任务。

为了简单起见,我们来处理这四个匹配项。五个数字中的哪个四个匹配并不重要,例如num5可以匹配val4val5,这使其变得更加复杂。

那么,有什么提示如何解决这个问题?我可以根据需要重组表,但必须使用MySQL。

2 个答案:

答案 0 :(得分:1)

如果您遵循“第一范式”并且不使用重复的列组,那么您的任务将会更轻松。

相反,创建另一个表,其中您的num列都是同一列。

CREATE TABLE numtable (
  groupid INT NOT NULL,
  num INT NOT NULL,
  PRIMARY KEY (groupid, num)
);

在此表中,您的旧表中的每一行最多可放置五行。如果要使用几列来存储可比较的值,则实际上您有一个多值属性,该属性必须在其自己的表中。

然后,您可以像这样查询以查找具有五个匹配项的groupid:

SELECT groupid
FROM numtable
WHERE num IN (@val1, @val2, @val3, @val4, @val5)
GROUP BY groupid
HAVING COUNT(*) = 5

然后替换最后一行以查找具有三个或四个匹配项的groupid,例如:

...
HAVING COUNT(*) = 4

如果您想知道许多个groupid的每个匹配数如何:

SELECT matches, COUNT(*) AS num_matches
FROM (
    SELECT groupid, COUNT(*) AS matches
    FROM numtable
    WHERE num IN (@val1, @val2, @val3, @val4, @val5)
    GROUP BY groupid
    HAVING COUNT(*) IN (3,4,5)
) AS t
GROUP BY matches

答案 1 :(得分:0)

Mysql计算布尔表达式为1或0,因此您可以像这样使用它们:

create table tablename(num1 int, num2 int, num3 int, num4 int, num5 int);
insert into tablename(num1, num2, num3, num4, num5) values
(1, 2, 3, 4, 5),
(1, 5, 10, 11, 85),
(1, 17, 23, 34, 45),
(1, 2, 3, 4, 6),
(1, 2, 3, 4, 7),
(1, 20, 30, 40, 50),
(1, 22, 32, 42, 55),
(1, 2, 3, 4, 5),
(10, 20, 30, 40, 50);

SET @val1 = 1;
SET @val2 = 2;
SET @val3 = 3;
SET @val4 = 4;
SET @val5 = 5;
SELECT t.matches, count(*) counter
FROM (
  SELECT 
    (num1 in (@val1, @val2, @val3, @val4, @val5)) + 
    (num2 in (@val1, @val2, @val3, @val4, @val5)) + 
    (num3 in (@val1, @val2, @val3, @val4, @val5)) + 
    (num4 in (@val1, @val2, @val3, @val4, @val5)) + 
    (num5 in (@val1, @val2, @val3, @val4, @val5)) matches
  FROM tablename
) t
GROUP BY t.matches
ORDER BY t.matches DESC 

子查询的每一行将包含列值和5个数字之间的匹配数。
因此,您可以根据此结果进行分组并计算每种情况。
请参见demo
对于Mysql 8.0+,您可以使用CTE:

SET @val1 = 1;
SET @val2 = 2;
SET @val3 = 3;
SET @val4 = 4;
SET @val5 = 5;
WITH cte as (
  SELECT @val1 val UNION ALL SELECT @val2 UNION ALL  
  SELECT @val3 UNION ALL SELECT @val4 UNION ALL SELECT @val5
)  
SELECT t.matches, count(*) counter
FROM (
  SELECT 
    (num1 in (SELECT val FROM cte)) + 
    (num2 in (SELECT val FROM cte)) + 
    (num3 in (SELECT val FROM cte)) + 
    (num4 in (SELECT val FROM cte)) + 
    (num5 in (SELECT val FROM cte)) matches
  FROM tablename 
) t
GROUP BY t.matches
ORDER BY t.matches DESC

请参见demo
结果:

| matches | counter |
| ------- | ------- |
| 5       | 2       |
| 4       | 2       |
| 2       | 1       |
| 1       | 3       |
| 0       | 1       |