【问题标题】:Querying from multiple tables based on runtime values根据运行时值从多个表中查询
【发布时间】:2020-08-30 12:58:08
【问题描述】:

我有一个模式如下:

一个基本实体可以有多个子实体,由 BaseChild 映射。在我的应用程序端,在持久化 Base 实体的同时,我持久化了相应的子实体。

例如:

  • 在基表中保持Base(id=1) 以及:
    • (ChildName='A', ChildValue=1) 用于 Child1 实体。
    • (ChildName='B', ChildValue='char') 用于 Child2 实体。
    • (ChildName='C', ChildValue=datetime()) 用于 Child3 实体。
    • (ChildName='D', ChildValue=5) 用于 Child1 实体。
  • 在基表中保留Base(id=2) 以及:
    • (ChildName='E', ChildValue=2) 用于 Child1 实体。
    • (ChildName='A', ChildValue=3) 用于 Child1 实体。
    • (ChildName='F', ChildValue='char') 用于 Child2 实体。

在各自的表中持久化后,

基表

+----+
| id |
+----+
|  1 |
|  2 |
+----+

BaseChild 表

+----------------------+
| id base_id ChildName |
+----------------------+
| 1    1        A      |
| 2    1        B      |
| 3    1        C      |
| 4    1        D      |
| 5    2        E      |
| 6    2        A      |
| 7    2        F      |
+----------------------+

Child1 表

+---------------+
| id ChildValue |
+---------------+
| 1  1          |
| 4  5          |
| 5  2          |
| 6  3          |
+---------------+

Child2 表

+---------------+
| id ChildValue |
+---------------+
| 2    'char'   |
| 7    'char'   |
+---------------+

Child3 表

+---------------+
| id ChildValue |
+---------------+
| 3  datetime() |
+---------------+

现在,在我的应用程序端,我收到一个查询,以获取基于 (ChildName, ChildValue) 值列表的 Base 实体的 id。

基本上是反向操作,现在我有一个子实体列表,我想找到与之对应的 Base 实体。 (请注意,子实体的数量不是固定的,例如 Base(id=1) 有 4 个子实体,但 Base(id=2) 有 3 个子实体)

让我们继续前面的例子。我收到一个查询说, 在 Child1 中找到与 (E,2) 对应的 (ChildName, ChildValue) 的基本实体的 id, (A,3) 在 Child1 中,(F,'char') 在 Child2 中。

对于这个查询,它应该获取Base(id=2)。

我应该如何在 sql server 中为这个动态查询建模?

我愿意接受任何对表格进行非规范化视图或对结果执行相交的想法。另外,我希望所有计算都在数据库端完成,而不是在我的应用程序端。

【问题讨论】:

  • 这些是 pk/fk 关系。不需要“实体”一词。解释一下你想要完成的事情会很有帮助。
  • 基表id上的基表还有其他关系。但是收到的查询是List<Childs> 类型的。所以我试图在基表中找到与 Childs 对应的id,然后使用该id 进行进一步处理。
  • 从数据库设计的角度来看,最好将 Childs 对象映射到表中的列。每个孩子没有单独的表格。
  • map Childs objects to columns in a table。您的意思是基表本身中的每个孩子都有一列?然后问题出现在具有空值并且每个子对象可以有多个子对象(如在示例中,Child1 中有2 条目用于Base(id=1)),因此每个字段将是一个数组而不是单个字段。
  • 不是“基表本身中每个子对象的列”,而是表中的行,其中包含充分定义对象的列,以便您可以获取任何想要的数组使用查询。

标签: sql sql-server database


【解决方案1】:

如果我理解正确,您可以使用exists 构造查询:

with c1 as (
      select bc.base_id, bc.childname, c1.*
      from child1 c1 join
           basechild bc
           on bc.id = c1.childvalue
     ),
     c2 as (
      select bc.base_id, bc.childname, c1.*
      from child1 c1 join
           basechild bc
           on bc.id = c1.childvalue
     )
select b.*
from base b
where exists (select 1
              from c1
              where c1.baseid = b.id and
                    c1.childname = 'E' and
                    c1.childvalue = 2
             ) and      
      exists (select 1
              from c1
              where c1.baseid = b.id and
                    c1.childname = 'A' and
                    c1.childvalue = 3
             ) and      
      exists (select 1
              from c2
              where c2.baseid = b.id and
                    c2.childname = 'F' and
                    c2.childvalue = 'char'
             );
      

【讨论】:

  • 谢谢,我使用了上述查询逻辑,并根据给定基础实体的子实体类型在我的应用程序端创建了一个原生查询。
猜你喜欢
  • 2022-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-18
相关资源
最近更新 更多