MySQL中非规范化表的查询
我有一组数组和一个mysql表,表1 $arr1=A0、A1、A2、A3、A4 $arr2=B0、B1、B2、B3、B4MySQL中非规范化表的查询,mysql,arrays,Mysql,Arrays,我有一组数组和一个mysql表,表1 $arr1=A0、A1、A2、A3、A4 $arr2=B0、B1、B2、B3、B4 +----+-----------------+------+------+ | id | Col1 | Col2 | Col3 | +----+-----------------+------+------+ | 0 | A0;B1;B2; | x | 9 | | 1 | A0;B1;B2;A1;A2; | x | 1
+----+-----------------+------+------+
| id | Col1 | Col2 | Col3 |
+----+-----------------+------+------+
| 0 | A0;B1;B2; | x | 9 |
| 1 | A0;B1;B2;A1;A2; | x | 15 |
| 2 | A0; | x | 7 |
| 3 | B0; | x | 5 |
| 4 | C0; | j | 5 |
+----+-----------------+------+------+
我是否可以查询表中的值,以便最终输出如下
+----+-------+------+
| id | C31T | C32T |
+----+-------+------+
| 0 | 19 | 17 |
+----+-------+------+
C31T和C32T来自此表
+----+------+------ +-------+------+------+
| id | Arr1 | Arr2 | C31 | C32 | tot |
+----+------+-------+-------+------+------+
| 0 | 1 | 2 | 3 | 6 | 3 |
| 1 | 3 | 2 | 9 | 6 | 5 |
| 2 | 1 | 0 | 7 | 0 | 1 |
| 3 | 0 | 1 | 0 | 5 | 1 |
+----+------+-------+-------+------+------+
按照eggyal的解决方案,我坚持到了这一点
SELECT table1.id,
COUNT(DISTINCT arr1.element) AS Arr1,
COUNT(DISTINCT arr2.element) AS Arr2,
COUNT(DISTINCT arr1.element) +
COUNT(DISTINCT arr2.element) AS tot,
(COUNT(DISTINCT arr1.element)/(COUNT(DISTINCT arr1.element)+COUNT(DISTINCT arr2.element)))*col3 AS c31,
(COUNT(DISTINCT arr2.element)/(COUNT(DISTINCT arr1.element)+COUNT(DISTINCT arr2.element)))*col3 AS c32
FROM table1
LEFT JOIN (
SELECT 'A0' AS element
UNION ALL SELECT 'A1'
UNION ALL SELECT 'A2'
UNION ALL SELECT 'A3'
UNION ALL SELECT 'A4'
) arr1 ON FIND_IN_SET(
arr1.element,
REPLACE(table1.Col1, ';', ',')
)
LEFT JOIN (
SELECT 'B0' AS element
UNION ALL SELECT 'B1'
UNION ALL SELECT 'B2'
UNION ALL SELECT 'B3'
UNION ALL SELECT 'B4'
) arr2 ON FIND_IN_SET(
arr2.element,
REPLACE(table1.Col1, ';', ',')
)
WHERE table1.Col2 = 'x'
GROUP BY table1.id
我完全同意-你真的应该考虑你的模式:
CREATE TABLE associations (
id INT,
element VARCHAR(2),
FOREIGN KEY (id) REFERENCES table1 (id)
);
INSERT INTO associations
(id, element)
VALUES
(0, 'A0'), (0, 'B1'), (0, 'B2'),
(1, 'A0'), (1, 'B1'), (1, 'B2'), (1, 'A1'), (1, 'A2'),
(2, 'A0'),
(3, 'B0'),
(4, 'C0')
;
ALTER TABLE table1 DROP Col1;
那么您的查询将是:
SELECT table1.id,
COUNT(DISTINCT arr1.element) AS Arr1,
COUNT(DISTINCT arr2.element) AS Arr2,
COUNT(DISTINCT arr1.element) +
COUNT(DISTINCT arr2.element) AS tot
FROM table1 JOIN associations USING (id)
LEFT JOIN (
SELECT 'A0' AS element
UNION ALL SELECT 'A1'
UNION ALL SELECT 'A2'
UNION ALL SELECT 'A3'
UNION ALL SELECT 'A4'
) arr1 USING (element)
LEFT JOIN (
SELECT 'B0' AS element
UNION ALL SELECT 'B1'
UNION ALL SELECT 'B2'
UNION ALL SELECT 'B3'
UNION ALL SELECT 'B4'
) arr2 USING (element)
WHERE table1.Col2 = 'x'
GROUP BY table1.id
SELECT table1.id,
COUNT(DISTINCT arr1.element) AS Arr1,
COUNT(DISTINCT arr2.element) AS Arr2,
COUNT(DISTINCT arr1.element) +
COUNT(DISTINCT arr2.element) AS tot
FROM table1
LEFT JOIN (
SELECT 'A0' AS element
UNION ALL SELECT 'A1'
UNION ALL SELECT 'A2'
UNION ALL SELECT 'A3'
UNION ALL SELECT 'A4'
) arr1 ON FIND_IN_SET(
arr1.element,
REPLACE(table1.Col1, ';', ',')
)
LEFT JOIN (
SELECT 'B0' AS element
UNION ALL SELECT 'B1'
UNION ALL SELECT 'B2'
UNION ALL SELECT 'B3'
UNION ALL SELECT 'B4'
) arr2 ON FIND_IN_SET(
arr2.element,
REPLACE(table1.Col1, ';', ',')
)
WHERE table1.Col2 = 'x'
GROUP BY table1.id
:
:
:
有点好玩
把你的桌子换成这样
Table1
+----+------+------+
| id | Col2 | Col3 |
+----+------+------+
| 0 | x | x |
| 1 | x | f |
| 2 | x | g |
| 3 | x | k |
| 4 | j | k |
+----+------+------+
Table2
+----+----------+------+
| id | Table1id | Col1 |
+----+----------+------+
| 0 | 0 | A0 |
| 1 | 0 | B1 |
| 2 | 0 | B2 |
| 3 | 1 | A0 |
| 4 | 1 | B1 |
| 5 | 1 | B2 |
| 6 | 1 | A1 |
| 7 | 1 | A2 |
| 8 | 2 | A0 |
| 9 | 3 | B0 |
| 10 | 4 | C0 |
+----+-----------------+
然后为查询创建一个临时表,其中包含以下内容:-
TempTable
+-------+----------+
| arrno | arrvalue |
+-------+----------+
| arr1 | A0 |
| arr1 | A1 |
| arr1 | A2 |
| arr1 | A3 |
| arr1 | A4 |
| arr2 | B0 |
| arr2 | B1 |
| arr2 | B2 |
| arr2 | B3 |
| arr2 | B4 |
+-------+----------+
SELECT table1.id, COUNT(TempTable1.arrvalue), COUNT(TempTable2.arrvalue), COUNT(*)
FROM table1
INNER JOIN table2
ON table1.id = table2.table1id
LEFT OUTER JOIN temptable TempTable1 ON table2.Col1 = TempTable1.arrvalue AND TempTable1.arrno = 'arr1'
LEFT OUTER JOIN temptable TempTable2 ON table2.Col1 = TempTable2.arrvalue AND TempTable2.arrno = 'arr2'
GROUP BY table1.id
然后可以像这样使用SQL:-
TempTable
+-------+----------+
| arrno | arrvalue |
+-------+----------+
| arr1 | A0 |
| arr1 | A1 |
| arr1 | A2 |
| arr1 | A3 |
| arr1 | A4 |
| arr2 | B0 |
| arr2 | B1 |
| arr2 | B2 |
| arr2 | B3 |
| arr2 | B4 |
+-------+----------+
SELECT table1.id, COUNT(TempTable1.arrvalue), COUNT(TempTable2.arrvalue), COUNT(*)
FROM table1
INNER JOIN table2
ON table1.id = table2.table1id
LEFT OUTER JOIN temptable TempTable1 ON table2.Col1 = TempTable1.arrvalue AND TempTable1.arrno = 'arr1'
LEFT OUTER JOIN temptable TempTable2 ON table2.Col1 = TempTable2.arrvalue AND TempTable2.arrno = 'arr2'
GROUP BY table1.id
有点晚了,但正在做其他事情,并且认为这可能对你也有帮助
设置一个名为integers的表,其中包含一个名为i的列。值为0到9的10行。然后,您可以使用下面的SQL语句来拆分单个字段
SELECT DISTINCT id, SUBSTRING_INDEX(SUBSTRING_INDEX(Col1, ';', anInteger), ';', -1) AS Col1_split, Col2, Col3
FROM table1,
(SELECT a.i*100+b.i*10+c.i AS anInteger FROM integers a, integers b, integers c) Sub1
HAVING Col1_split <> ''
这可能有助于将分隔字段复制到另一个表中,或者如果您不顾一切,您可以将其用作自己SQL中的子选择,而不是直接使用该表。不太可能,可能需要一些非常糟糕的编码。我建议将这两个数组的内容放入一个临时表中,每个数组元素一行,这样这两个数组就意味着10行,然后使用like将临时表与现有表连接起来。不过,它的表现将非常糟糕。正确的解决方案需要重新设计您的表以摆脱分号分隔的列表,将它们放在各自的表中,每个元素一行,以便您可以轻松地在表之间联接。@Kickstart,谢谢,将尝试重新设计我的表修改我的答案,可能有助于您将数据提取到重新设计的表中。不确定这是否违反SO中的规则,但我更新了原始帖子中的所需输出。。。我研究了我们现有的表,但由于一些页面已经依赖于当前的模式,因此无法很容易地正常化。。更改它需要我们另一次时间来检查现有页面。我遵循了eggyal的解决方案,但是我仍然停留在如何从Col3中获取与令牌发现数量相关的值上。谢谢,我尝试在1个查询中提取我需要的所有内容时失败了
SELECT table1.id, COUNT(TempTable1.arrvalue), COUNT(TempTable2.arrvalue), COUNT(*)
FROM table1
INNER JOIN table2
ON table1.id = table2.table1id
LEFT OUTER JOIN temptable TempTable1 ON table2.Col1 = TempTable1.arrvalue AND TempTable1.arrno = 'arr1'
LEFT OUTER JOIN temptable TempTable2 ON table2.Col1 = TempTable2.arrvalue AND TempTable2.arrno = 'arr2'
GROUP BY table1.id
SELECT DISTINCT id, SUBSTRING_INDEX(SUBSTRING_INDEX(Col1, ';', anInteger), ';', -1) AS Col1_split, Col2, Col3
FROM table1,
(SELECT a.i*100+b.i*10+c.i AS anInteger FROM integers a, integers b, integers c) Sub1
HAVING Col1_split <> ''