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应该返回
['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;