当前位置: 首页 > 面试题库 >

MySQL:在一个Statement上连接许多表

田阳泽
2023-03-14
问题内容

我有以下数据库结构/层次结构:

TABLE product_type

id,name, ....

TABLE product

id,parent_id, name, ...

parent_id :是product_type ID

TABLE treeNode

id, parent_id, name, type

它是一个树层次结构(根有n个子节点),层次结构的数量 未知

coltype的值为 “ CATEGORY”“ GROUP” ,这意味着我有2棵树:

Categories:

   TreeNode 1
         sub 1.1
                sub.1.1.1
                sub.1.1.2
                  ....
         sub 1.2
                sub.1.2.1
                sub.1.2.2
                  ....
   TreeNode 2
         sub 2.1
                sub.2.1.1
                sub.2.1.2
                  ....
         sub 2.2
                sub.2.2.1
                sub.2.2.2
                  ....

Groups:

   TreeNode 1
         sub 1.1
                sub.1.1.1
                sub.1.1.2
                  ....
         sub 1.2
                sub.1.2.1
                sub.1.2.2
                  ....
   TreeNode 2
         sub 2.1
                sub.2.1.1
                sub.2.1.2
                  ....
         sub 2.2
                sub.2.2.1
                sub.2.2.2
                  ....

TABLE linked_treeNode:

product_id, treeNode_id

现在说,用户选择:

1:a product type(PARAM: $selected_type

2:a category(PARAM: $selected_cat

3:a group(PARAM: $selected_group

现在,我想展示符合这些选择的 all Products

1-)链接到选定的类别或子类别

2-)链接到选定的组或其子组

3-)链接到选定的产品类型

什么是 MySQL的 的发言(1个报表)?

我尝试了这个:

SELECT P.* FROM 
product P, treeNode C, treeNode G, linked_TreeNode LC
WHERE 
p.parent_id='$selected_type' 
AND
( 
       C.type='CATEGORY' 
       AND 
       C.parent_id='$selected_cat' 
       AND 
       P.id=LC.product_id 
       AND 
       (LC.treeNode_id=C.id OR LC.treeNode_id='$selected_cat') 
)
AND
( 
       G.type='GROUP' 
       AND 
       G.parent_id='$selected_group' 
       AND 
       P.id=LC.product_id 
       AND 
       (LC.treeNode_id=G.id OR LC.treeNode_id='$selected_group') 
)
;

但是我总是得到0结果!

我用JOINS ..etc尝试了许多其他Statements(更改)。但没有成功。

非常感谢

编辑:我上面使用的语句是错误的,所以不要使用它!


问题答案:

对于MySql来说,这确实是一个问题,这是解决这个问题的关键,但是您仍然可以选择。

假设您拥有这样的样本数据,但不像样本那么多,但足以证明:

create table treeNode(
id int, parent_id  int,  name varchar(10), type varchar(10),level int);
insert into treeNode 
(id, parent_id, name, type, level) values 
( 1,  0,  'C1    ', 'CATEGORY', 1),
( 2,  1,  'C1.1  ', 'CATEGORY', 2),
( 3,  2,  'C1.1.1', 'CATEGORY', 3),
( 4,  1,  'C1.2  ', 'CATEGORY', 2),
( 5,  4,  'C1.2.1', 'CATEGORY', 3),
( 3,  8,  'G1.1.1',    'GROUP', 3),
( 4,  9,  'G1.2  ',    'GROUP', 2),
( 5,  4,  'G1.2.1',    'GROUP', 3),
( 8,  9,  'G1.1  ',    'GROUP', 2),
( 9,  0,  'G1    ',    'GROUP', 1);

首选: 等级码

类似于treeNode表中name列的示例数据。( 我不知道该怎么说英语,请就。的正确表达对我进行评论level code。)

要获得C1或的所有后代,G1可能会像这样简单:

select * from treeNode where type = 'CATEGORY' and name like 'C1%' ;
select * from treeNode where type = 'GROUP' and name like 'G1%' ;

我非常喜欢这种方法,甚至需要我们在treeNode保存到应用程序之前生成这些代码。当我们有大量记录时,它将比递归查询或过程更有效。我认为这是一种很好的非规范化方法。

使用这种方法,您想要 加入* 的语句 可以是: *

SELECT distinct p.* --if there is only one tree node for a product, distinct is not needed
FROM product p
JOIN product_type pt
     ON pt.id= p.parent_id -- to get product type of a product
JOIN linked_TreeNode LC
     ON LC.product_id= p.id -- to get tree_nodes related to a product
JOIN (select * from treeNode where type = 'CATEGORY' and name like 'C1%' ) C --may replace C1% to concat('$selected_cat_name','%')
     ON LC.treeNode_id = C.id
JOIN (select * from treeNode where type = 'GROUP' and name like 'G1%' ) G --may replace G1% to concat('$selected_group_name','%')
     ON LC.treeNode_id = G.id
WHERE pt.name = '$selected_type'  -- filter selected product type, assuming using product.name, if using product.parent_id, can save one join by pt like your original sql

亲爱的,不是吗?

第二选择:等级编号

如DDL中所示,将一个级别列附加到treeNode表。

级别编号比应用程序中的 级别代码 容易维护。

使用级别号来获取所有后代C1G1需要一些技巧:

SELECT id, parent_id, name, type, @pv:=concat(@pv,',',id) as link_ids 
  FROM (select * from treeNode where type = 'CATEGORY' order by level) as t
  JOIN (select @pv:='1')tmp
 WHERE find_in_set(parent_id,@pv)
    OR find_in_set(id,@pv);
 -- get all descendants of `C1`

SELECT id, parent_id, name, type, @pv:=concat(@pv,',',id) as link_ids 
  FROM (select * from treeNode where type = 'GROUP' order by level) as t
  JOIN (select @pv:=',9,')tmp
 WHERE find_in_set(parent_id,@pv)
    OR find_in_set(id,@pv) ;

这种方法比第一种慢,但比递归查询快。

该问题的完整sql省略了。只需要用上面的两个查询替换C和G的那两个子查询。

笔记:

除非按级别编号或级别代码订购,否则它们将无法工作。您可以测试在这个最后的查询[SqlFiddle](http://sqlfiddle.com/#!2/8150e/12)
,通过改变order by levelorder by id看到的差异。

另一个选择:嵌套集模型

请参考此博客,我尚未测试。但是我认为这类似于最后两个选择。

它需要在treenode表中添加一个左数字和一个右数字,以将它们之间的所有后代ID括起来。



 类似资料:
  • 问题内容: 我从来没有做过这样的PHP / MYSQL技巧来加入多表。请具有该领域经验的人员帮助: TICKETS 表中的字段: 表 RECEPTS中的 字段: 表 PAYMENTS中的 字段: 表 CUSTOMERS中的 字段: 表之间的关系很容易理解: 我希望达到的最终结果: 我试图做这样的事情,但在某个地方出错: 问题答案: 您应该可以使用以下方法获得结果: 参见带有演示的SQL Fiddl

  • 问题内容: 如您所见,我在数据库连接上遇到问题。它给了我这个错误: …由于许多连接错误而被阻止 我搜索了一些答案,但无法解决问题。 我不知道我是否提供了您需要的所有信息,所以如果您需要其他信息,请告诉我。我有来自不同计算机的数据库连接,并且创建了一个用户来访问该数据库,但该用户位于主机行中,因此我想使用IP地址更改它以解决安全问题,因此出现了此错误,因此我卡住。 问题答案: MySQL会阻止连接时

  • Flink社区! 我有一个关于在Flink中连接相同键上的多个流的问题(等连接)。我还是一个新手,正在为我的团队评估Flink,将我们的Spark批处理应用程序迁移到流处理。 注意:我看了FabianHüske的这篇关于加入处理的文章:窥视Apache Flink的引擎室。 为了简化问题,假设您有3个流,每个流都有唯一的记录,可以通过id字段进行键控。对于流中的每条记录,您将在其他流中找到相应的记

  • 问题内容: 我的信息分布在几个数据库中,并希望使用PHP将所有信息放到一个网页上。我想知道如何在单个PHP网页上连接到多个数据库。 我知道如何使用以下方法连接到单个数据库: 但是,我可以仅使用多个“ mysql_connect”命令来打开其他数据库吗?如果我确实连接了多个数据库,PHP如何知道要从哪个数据库中提取信息? 问题答案: 警告: 自php 5.5起不推荐使用功能,自php 7.0起不推荐

  • 问题内容: 因此,这更多是一个设计问题。 我有一个主键(例如用户的ID),并且有大量与该用户相关联的信息。 我应该根据信息将多个表细分为几类,还是只有一个表包含许多列? 我过去这样做的方法是拥有多个表,例如,一个表用于应用程序使用情况数据,一个表用于配置文件信息,一个表用于后端令牌等,以使事情看起来井井有条。 最近有人告诉我,最好不要那样做,有一个包含很多列的表也可以。关键是,所有这些列都具有相同

  • 我有三个表,一个用于用户的表,一个用于订单,最后一个包含订单项。 我创建了一个SQL查询,用于获取所有订单并将用户加入结果,现在我想将订单项加入查询。一个订单可以有多个订单项。每个订单项目都有一个价格。我需要与订单项目对应的所有订单项目的总和。 所以我会得到一个结果,看起来像这样:id,order_id, userid,order_time, id, name, email, price 现在,我