Mysql 获取包含特定单元格中输入值的行,按其他单元格筛选,返回其他单元格值
多亏了前面的一个问题,我在数据库Mysql 获取包含特定单元格中输入值的行,按其他单元格筛选,返回其他单元格值,mysql,postgresql,mysqli,Mysql,Postgresql,Mysqli,多亏了前面的一个问题,我在数据库dab中有一个表tab,它由四列组成。一个简单的ID列(ID)也是主键(int),一个pat列(varchar(255)),一个path列(varchar(191)),最后一个has_tree(位(1)) 给定一个pat值(如果存在),我想要 所有唯一的pat值(包括输入的树==1) 其中其路径包含输入的路径 其中的树==1 所以输入AA应该返回['AA','ABA','ABCA','ABC'] 重要说明是,输入pat的路径不一定是单个项目的“根路径”,换句话
dab
中有一个表tab
,它由四列组成。一个简单的ID列(ID
)也是主键(int),一个pat
列(varchar(255)),一个path
列(varchar(191)),最后一个has_tree
(位(1))
给定一个pat
值(如果存在),我想要
- 所有唯一的
值(包括输入的pat
)树==1
- 其中其路径包含输入的路径
- 其中
的树==1
['AA','ABA','ABCA','ABC']
重要说明是,输入pat
的路径不一定是单个项目的“根路径”,换句话说:很可能输入的path
类似于1/12/45/966
,在这种情况下,我需要所有唯一的pat
值,其中path
是1/12/45/966
的后代,有_树
是1
。另一个注意事项是路径可能非常深,因此即使输入path
为1
,结果也可能更深很多层次,例如1/22/36/88/98/455/878/1205/2555
Paul提出了以下查询,该查询适用于提议的数据结构,但是您可以看到当前的结构和需求略有不同。(还请注意,我有一个数据库和多个表。因此,在数据库dab
中给定一个表tab
,我希望执行脚本。)
我试图用PHP实现这一点,然后调用一些SQL数据库是否可以以通用、性能良好的形式编写此文件,以使其适用于PostgreSQL、MySQL(i)和其他版本?如果不能,我至少希望看到MySQLi和PostgreSQL的变体
在上面Paul的示例代码的基础上,我认为应该是这样的,但我不确定我也不确定为什么需要使用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\u 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
演示:
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
演示:
注意:正如您将在domo中看到的,如果您使用以下命令更改模式,您还可以在MySQL中使用管道(|
)进行连接:
SET sql_mode=PIPES_AS_CONCAT;
关于索引:布尔列上的索引通常不是很有用。但是,只有测试它,您才能确定。对于给定的查询,(has_tree,path)
上的复合索引可能会提高性能。谢谢,这非常有效,而且速度很快!我总是很惊讶SQL是怎样的。与主题问题稍有不同的是,路径上的唯一索引与路径上的“常规”索引之间的差异在数百万行中是否明显?@BramVanroy对于SELECT语句,应该没有任何区别。使用唯一索引时,插入和更新可能会稍微慢一点。但是再一次——只有在测试它(或者分析实现)时,您才能确定。然而,我可能总是这样定义逻辑上唯一的列。看看有多少像“我如何删除重复项?”这样的问题被问到,因为人们没有定义正确的唯一键。
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
SET sql_mode=PIPES_AS_CONCAT;