【问题标题】:Hierarchical query in SQL ServerSQL Server 中的分层查询
【发布时间】:2021-07-12 00:50:00
【问题描述】:

我只能访问视图。我无法访问表格。

关系视图包含分层格式的元数据。

包含

  • 列到表的关系
  • 表与架构关系
  • 表/架构与数据库的关系
  • 表/架构/数据库与系统的关系

obj id & type 和 parent obj id & type 定义层次结构。

对象视图包含对象名称、类型等元数据属性。

表可以存在于架构、数据库或系统中。

Relation 返回非常庞大的数据集 - 数以亿计。因此,我试图避免自我加入。

版本 - Microsoft SQL Server 2014 (部分功能不支持)

关系:

+------------+--------------------+------------+---------------------+
| object_id1 | object_type_name1  | object_id2 | object_type_name2   |
+------------+--------------------+------------+---------------------+
| 1          |  table             | 100        |  schema             |
| 100        |  schema            | 200        |  database           |
| 200        |  database          | 300        |  system             |
| 2          |  table             | 201        |  database           |
| 201        |  database          | 301        |  system             |
| 3          |  table             | 302        |  system             |
| 4          |  column            | 1          |  table              |
| 5          |  column            | 1          |  table              |
| 6          |  column            | 1          |  table              |
| 7          |  column            | 1          |  table              |
| 8          |  column            | 1          |  table              |
| 9          |  column            | 1          |  table              |
| 10         |  column            | 2          |  table              |
| 11         |  column            | 2          |  table              |
| 12         |  column            | 2          |  table              |
| 13         |  column            | 3          |  table              |
| 14         |  column            | 3          |  table              |
| 15         |  column            | 3          |  table              |

obj_属性:

+-------------+---------------+---------------+
|  Object_id  |  Object_Name  |  Object_Type  |
+-------------+---------------+---------------+
| 1           |  Table_A      |  table        |
| 2           |  Table_B      |  table        |
| 3           |  Table_C      |  table        |
| 4           |  Col_A        |  column       |
| 5           |  Col_B        |  column       |
| 6           |  Col_C        |  column       |
| 7           |  Col_D        |  column       |
| 8           |  Col_E        |  column       |
| 9           |  Col_F        |  column       |
| 10          |  Col_G        |  column       |
| 11          |  Col_H        |  column       |
| 12          |  Col_I        |  column       |
| 13          |  Col_J        |  column       |
| 14          |  Col_K        |  column       |
| 15          |  Col_L        |  column       |
| 100         |  Schema1      |  schema       |
| 200         |  DB1          |  database     |
| 201         |  DB2          |  database     |
| 300         |  System1      |  system       |
| 301         |  System2      |  system       |
| 301         |  System3      |  system       |
| 302         |  System4      |  system       |

我们的要求是开发一个以以下格式显示元数据的查询:

带有属性的输出:

+---------+----------+---------+---------+--------+
| system  | database | schema  | table   | column |
+---------+----------+---------+---------+--------+
| System1 | DB1      | Schema1 | Table_A | Col_A  |
| System1 | DB1      | Schema1 | Table_A | Col_B  |
| System1 | DB1      | Schema1 | Table_A | Col_C  |
| System1 | DB1      | Schema1 | Table_A | Col_D  |
| System1 | DB1      | Schema1 | Table_A | Col_E  |
| System1 | DB1      | Schema1 | Table_A | Col_F  |
| System2 | DB2      | ?       | Table_B | Col_G  |
| System2 | DB2      | ?       | Table_B | Col_H  |
| System2 | DB2      | ?       | Table_B | Col_I  |
| System4 | ?        | ?       | Table_C | Col_J  |
| System4 | ?        | ?       | Table_C | Col_K  |
| System4 | ?        | ?       | Table_C | Col_L  |

带有对象 ID 的输出:

+--------+----------+--------+-------+--------+
| system | database | schema | table | column |
+--------+----------+--------+-------+--------+
| 300    | 200      | 100    | 1     | 4      |
| 300    | 200      | 100    | 1     | 5      |
| 300    | 200      | 100    | 1     | 6      |
| 300    | 200      | 100    | 1     | 7      |
| 300    | 200      | 100    | 1     | 8      |
| 300    | 200      | 100    | 1     | 9      |
| 301    | 201      | ?      | 2     | 10     |
| 301    | 201      | ?      | 2     | 11     |
| 301    | 201      | ?      | 2     | 12     |
| 302    | ?        | ?      | 3     | 13     |
| 302    | ?        | ?      | 3     | 14     |
| 302    | ?        | ?      | 3     | 15     |

有人可以帮忙实现这个输出吗?

更新:我试图在意识到数据量之前提出查询 - 但查询因内存问题而失败

with objt as (select * from obj_Attribute)

select 
(select object_name from objt where object_id=tbl_id) as tbl_nm,
(select object_name from objt where object_id=col_id) as col_nm,
(select object_name from objt where object_id=schema_id) as sc_nm,
(select object_name from objt where object_id=db_id) as db_nm,
(select object_name from objt where object_id=sy_id) as sy_nm
 
from (
   select 
      tbl.object_id1 as tbl_id,
      col.object_id1 as col_id,
      case when sc.object_type1='Schema' then sc.object_id1 end as schema_id,
      case when db.object_type1='Database' then db.object_id1 
      when sc.object_type1='Database' then sc.object_id1 
      end as db_id,
      case when sy.object_type1='System' then sy.object_id1 
      when db.object_type1='System' then db.object_id1 
      when sc.object_type1='System' then sc.object_id1 
      end as sy_id
   from 
   relation tbl 

   left outer join relation sc
   on tbl.object_id2 = sc.object_id1

   left outer join relation db
   on sc.object_id2 end = db.object_id1

   left outer join relation sy
   on else db.object_id2 = sy.object_id1

   left outer join relation col
   on col.object_id2=tbl.object_id1
   and col.object_type1='Column'

   where tbl.object_type1 in ('Table', 'View', 'Database View')
) subqry

【问题讨论】:

  • 您的查询与您的示例数据不匹配。请纠正。你也加入了Relation.obj_id1object_id?),这不是唯一的。对吗?
  • 感谢您的通知 - 我更新了查询以匹配示例数据。是的 - JOIN 基于 object_id,因为层次结构可以达到 4 个级别 - Tables to schema to database to system 并且它们不一致。因此我没有找到其他选择
  • 这两行2 | table | 201 | database2 | column | 1 | table对吗?然后你需要加入object_id1 = .. and object_type_name1=..
  • 请原谅我 - 这是不正确的 - 我现在更新了数据样本。 .

标签: sql-server hierarchy


【解决方案1】:

在系统级别使用自连接统计。要获得姓名,请在最后加入obj_Attribute

with sys as (
    select * from obj_Attribute where  Object_Type = 'system' 
)
select s.Object_id systemId
   , case 'database' when r1.object_type_name1 then r1.object_id1 end dbId
   , case 'schema' when r1.object_type_name1 then r1.object_id1  
                   when r2.object_type_name1 then r2.object_id1 
     end schemaId
   , case 'table' when r1.object_type_name1 then r1.object_id1 
                  when r2.object_type_name1 then r2.object_id1
                  when r3.object_type_name1 then r3.object_id1
     end  tableId
   , case 'column' when r1.object_type_name1 then r1.object_id1 
                   when r2.object_type_name1 then r2.object_id1
                   when r3.object_type_name1 then r3.object_id1
                   when r4.object_type_name1 then r4.object_id1
     end  columnId    
from sys s
left join Relation r1 on s.Object_id = r1.object_id2
left join Relation r2 on r1.Object_id1 = r2.object_id2
left join Relation r3 on r2.Object_id1 = r3.object_id2
left join Relation r4 on r3.Object_id1 = r4.object_id2

如果这很耗费资源,您可以尝试分几个步骤进行。例如,推迟最后一步:

with sys as (
    select * from obj_Attribute where  Object_Type = 'system' 
)
select s.Object_id systemId
   , case 'database' when r1.object_type_name1 then r1.object_id1 end dbId
   , case 'schema' when r1.object_type_name1 then r1.object_id1  
                   when r2.object_type_name1 then r2.object_id1 
     end schemaId
   , case 'table' when r1.object_type_name1 then r1.object_id1 
                  when r2.object_type_name1 then r2.object_id1
                  when r3.object_type_name1 then r3.object_id1
     end  tableId
   , case 'column' when r1.object_type_name1 then r1.object_id1 
                   when r2.object_type_name1 then r2.object_id1
                   when r3.object_type_name1 then r3.object_id1
     end  columnId
   , r3.object_id1 r3_id1
INTO #Temp
from sys s
left join Relation r1 on s.Object_id = r1.object_id2
left join Relation r2 on r1.Object_id1 = r2.object_id2
left join Relation r3 on r2.Object_id1 = r3.object_id2;
--left join Relation r4 on r3.Object_id1 = r4.object_id2
  
select t.systemId, t.dbId, t.schemaId, t.tableId, coalesce(t.columnId, r4.object_id1) columnId
from #temp t
left join Relation r4 on t.r3_id1 = r4.object_id2;

【讨论】:

  • 谢谢军士。如果它是具有正确索引集的表,我会进行自连接。由于这是一个视图 - 如果我进行自我加入 - 查询运行时间更长并且因内存问题而失败
  • 您也可以尝试递归 CTE。不确定它会消耗更少的资源。您还可以将视图实例化为临时表并构建索引。
猜你喜欢
  • 2010-09-19
  • 1970-01-01
  • 1970-01-01
  • 2010-11-24
  • 1970-01-01
  • 1970-01-01
  • 2010-10-03
  • 1970-01-01
相关资源
最近更新 更多