-3

考虑一个带有 2 个表的数据库,如下所示。CompanyIdDepartment表中指向的外键Company。公司名称是唯一的,但部门名称不是。

桌子 :Department

+-------+-----------+-----------+-------------------+
|   id  |   name    | CompanyId |       phone       |
+-------+-----------+-----------+-------------------+
|   1   |   Sales   |       1   |   214-444-1934    |
|   2   |   R&D     |       1   |   555-111-1834    |
|   3   |   Sales   |       2   |   214-222-1734    |
|   4   |   Finance |       2   |   817-333-1634    |
|   5   |   Sales   |       3   |   214-555-1434    |
+-------+-----------+-----------+-------------------+

桌子 :Company

+-------+-----------+
|   id  |   name    |  
+-------+-----------+
|   1   |   Best1   |
|   2   |   NewTec  | 
|   3   |   JJA     |
+-------+-----------+

我有一个像下面这样的过滤器。当部门名称为空(空)时,这意味着该公司的所有部门 ID 都应包含在结果中,但当有列表时,它应仅包含列出的那些。

    [ {
        companyName: "Best1",
        departmentName: ["Sales", "R&D"]
      },
      {
        companyName: "NewTec",
        departmentName: ["Finance"]
      } ,
      {
        companyName: "JJA",
        departmentName: null
      } 
    }]

注意:过滤器是动态的(对 API 端点的请求),可能包括数千个公司和部门。

我想要一个 sql 查询来返回所有符合条件的部门 id。对于此示例,结果将是“1,2,4,5”。(返回除 NewTec 销售部门的 id (3) 之外的所有部门 id)

我正在寻找有效的 SQL 和/或 linq 查询来返回结果。我可以遍历公司并为每个单独的部门过滤掉部门,但这意味着对于每个公司来说,将使用 ORM 访问一次数据库。有没有更好的方法来处理这种情况?

4

2 回答 2

1

这是您想要的 SQL 查询:

SELECT
    d.id
FROM Department d
INNER JOIN Company c
    ON d.CompanyId = c.id
WHERE
    (c.name = 'Best1' AND d.name IN ('Sales', 'R&D')) OR
    (c.name = 'NewTec' AND d.name = 'Finance') OR
    c.name = 'JJA';

演示

于 2019-09-13T05:14:02.340 回答
0

您想要处理数量不定的条件。解决这个问题主要有两种方法:

  1. 根据您的条件动态构建查询字符串。
  2. 将条件放在单独的表中并针对该表进行查询。

使用这样的过滤器表:

公司名称 | 部门名称
-------------+----------------
最佳1 | 销售量
最佳1 | 研发
新科技 | 金融
JJA | (空值)

不变的(!)查询将是:

SELECT *
FROM Department d
INNER JOIN Company c ON d.CompanyId = c.id
WHERE EXISTS
(
  SELECT *
  FROM Filter f
  WHERE f.company_name = c.name
  AND (f.department_name = d.name OR f.department_name IS NULL)
);

这是一个演示:https ://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=49ff15426776536acc6f5bd7f88aaf8f (我为此劫持了蒂姆的演示:-)

这里有一个想法如何结合上面提到的两种方法: 使过滤表成为一个临时视图,即将它放在一个WITH子句中。但是为了保持查询不变,您WITH从执行动态部分的存储过程中填充该子句。存储过程将读取包含条件的 XML 并从中选择行。因此,您可以让您的 ORM 调用此过程来获得您想要的结果。

这是一个解释如何在存储过程中从 XML 获取输入的查询的线程:从 SQL Server 存储过程中的 XML 输入参数创建查询并验证输出

然后查询看起来像:

WITH Filter AS (SELECT company_name, department_name FROM dbm.GetMyFilterDataFromXml(@Xml))
SELECT *
FROM Department d
INNER JOIN Company c ON d.CompanyId = c.id
WHERE EXISTS
(
  SELECT *
  FROM Filter f
  WHERE f.company_name = c.name
  AND (f.department_name = d.name OR f.department_name IS NULL)
);
于 2019-09-13T06:07:10.743 回答