感谢Paul Spiegel's answer关于上一个问题,我有一张 table tab
在数据库中dab
它由四列组成。一个简单的,一个 ID 列 ( id
),也是主键 (int),一个 pat
列 (varchar(255)),a path
列 (varchar(191)),最后是 has_tree
(位(1))。
id pat path has_tree
1 AA 1 1
2 ABA 1/2 1
3 ABCA 1/3 1
4 ABA 1/5 0
5 AB 2 0
6 BBB 2/1 1
7 CAB 2/2 1
8 ABC 1/4 0
9 ABC 1/5/7 1
10 ABA 3/2 1
给定 pat
值(如果存在),我想要
- 全部都是独一无二的
pat
值(包括输入的has_tree==1
), - 其中它们的路径包含输入的路径,
- 哪里
has_tree == 1
.
因此输入 AA 应返回 ['AA', 'ABA', 'ABCA', 'ABC']
.
重要说明是 path
输入pat
不一定是单个项目“根路径”,换句话说:输入 path
很可能是类似于 1/12/45/966
在这种情况下,我想要所有独特的 pat
值其中 path
是 1/12/45/966
的后代哪里 has_tree
是 1
。另外需要注意的是,路径可以很深,所以即使输入path
是 1
,结果可以更深层次,例如1/22/36/88/98/455/878/1205/2555
.
Paul 建议使用以下查询,该查询适用于建议的数据结构,但是正如您所看到的,当前的结构和要求略有不同。 (另请注意,我有一个包含多个表的数据库。因此,给定数据库 tab
中的一个表 dab
我想执行该脚本。)
SELECT t.*
FROM tree t
CROSS JOIN tree r -- root
WHERE r.CELL = '3B0'
AND t.path LIKE CONCAT(r.path, '%');
我正在尝试使用 PHP 来执行此操作,然后调用一些 SQL 数据库。 是否可以以通用、高性能的形式编写它,以便它适用于 PostgreSQL、MySQL 和其他版本?如果没有,我至少希望看到 MySQL 和 PostgreSQL 变体。
基于保罗上面的示例代码,我认为这会是这样的,但我不确定。 我也不确定为什么 JOIN
运算符是必要的以及它在这种情况下的作用(我知道它通常做什么,但不知道为什么在这种情况下是必要的)。我确信这段代码可以得到改进、修复,并使其对于所有 SQL 风格更加通用?此外,我没有看到我下面的尝试包含当前输入 pat
在输出中。
SELECT t.pat
FROM `tab` t
JOIN `tab` r
WHERE r.pat = 'AA' -- input
AND t.path LIKE CONCAT(r.path, '/', '%')
AND t.has_tree = 1;
额外问题:我已对除 has_tree
之外的所有列建立索引。对该列建立索引也会有好处吗?
最佳答案
第一个注意事项:路径应以反斜杠结尾('1/'
、'1/2/'
而不是 '1'
和'1/2'
)。这很重要,因为否则您无法匹配子树的根。示例:
WHERE path LIKE '1/%'
不会匹配'1'
,但会匹配'1/'
。
您也可以不只是跳过查询中的反斜杠:
WHERE path LIKE '1%'
将匹配根'1'
,但也会匹配'10..'
现在回答你的问题:如果你已经知道根节点的路径,则不需要联接:
SELECT * FROM tab WHERE path LIKE '1/%' AND has_tree
要仅获得“独特”的拍拍,您可以使用DISTINCT
关键字:
SELECT DISTINCT pat
FROM tab
WHERE path LIKE '1/%'
AND has_tree
就是这样。
如果您不知道根路径,只知道 pat
值,则需要运行两个查询(首先获取路径,然后获取后代)或使用联接。
PostgreSQL:
SELECT DISTINCT t.pat
FROM tab t
JOIN tab r ON t.path LIKE r.path || '%'
WHERE r.pat = 'AA' -- input
AND t.has_tree
演示:http://rextester.com/EXZT43019
MySQL:
SELECT DISTINCT t.pat
FROM tab t
JOIN tab r ON t.path LIKE CONCAT(r.path, '%')
WHERE r.pat = 'AA' -- input
AND t.has_tree
演示:http://rextester.com/DNHRJ83456
注意:正如您将在 domo 中看到的,如果您更改模式,您还可以在 MySQL 中使用管道 (||
) 进行连接:
SET sql_mode=PIPES_AS_CONCAT;
关于索引: bool 列上的索引通常不是很有用。然而,只有测试后才能确定。对于给定的查询,(has_tree, path)
上的复合索引可能会提高性能。
关于mysql - 获取包含特定单元格中输入值的行,按其他单元格过滤,返回其他单元格值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42519660/