【问题标题】:How to get the correct SQL result in complex sql with 4 tables如何在具有 4 个表的复杂 sql 中获得正确的 SQL 结果
【发布时间】:2018-09-26 14:40:19
【问题描述】:

我们有一个 sql 查询,我们使用 3 个内部连接和一个非常复杂的 where 条件。我们有以下 4 个表:
表 1:Avis - 它是表 2 的 1:n(绑定在 Avis.Id=Item.AvisFk)
表 2:项目 - 它是表 3 的 1:n(绑定在 Item.Id=Routesection.ItemFk)
表 3:Routesection - 它是表 4 的 n:1(绑定在 Routesection.TourFk=Tour.Id)
表 4:游览

现在我们使用 WHERE 条件过滤一些日期、位置等。现在我们遇到了问题,我们不想拥有一些特殊的 Item-Id。我们得到一些错误的结果。 存在具有许多项目的 Avis。现在我们要过滤所有至少有一个不想要的项目的 Avis。但来自 Tour-Query。

我试过了 WHERE (SELECT Count(*) FROM Item WHERE OemFk=5003 AND AvisFK = Avis.Id) = 0 但是我们必须使用一些 GROUP BY's 并且我们将所有 Avis 分组到一个 Tour.Id 以便我们每次都得到一个“真实”,因为在这个 Tour 中有一些 Avis 有不想要的项目而有些没有.. .

有人知道我该如何解决这个问题吗?

编辑: 好的,我试着给你一个基本的我真正的意思。假设我们在 Avis 中有 2 个数据行。行:ID; (只有真正需要的)
1;
2;
然后假设我们在 Item 中有一些项目。行:ID; AvisFk; OemFk;
1; 1; 5001;
2; 1; 5002;
3; 2; 5003;
4; 2; 5004;
然后是Routesection(多一点行,我这里只放一些供示例参考)。行:ID;项目Fk; TourFk;
1; 1; 1;
2; 1; 1;
3; 2; 1;
4; 2; 1;
5; 3; 2;
6; 3; 2;
7; 4; 3;
8; 4; 3;
最后但并非最不重要的巡回赛。行:ID;
1;
2;
3;
好的,现在我要查询 Tour 表。结果应该只有 Tour 1。期望的结果是获得其他表上的内部连接与特殊条件无关的游览。条件是:如果一个项目具有 OemFk 5003,那么来自同一个 Avis(在本例中为 3 和 4)的所有项目都必须被过滤掉。 SELECT 引用了近 40 列,WHERE 包括 5 个以上的条件,并且 SELECT 中的每一列也在 GROUP BY 内,所以我试图只显示所需的最小值而不是完整的查询。

【问题讨论】:

  • 样本数据和期望的结果真的很有帮助。
  • 如果可能,尝试添加sql fiddle
  • 这不只是需要一个“有”子句吗?
  • 在未发布查询时很难帮助查询。只是说'
  • 使用 WITH 命令将您的表格预过滤为 4 个 CTE 表达式,然后使用您想要的数据,加入 CTE 'tables' - 是一个建议

标签: sql sql-server tsql group-by where-clause


【解决方案1】:

...此巡回赛中有一些 Avis 有不想要的项目和 有些不...

有人知道我该如何解决这个问题吗?

研究使用 WHERE EXISTS()。

【讨论】:

  • 我已经试过了,但问题和上面一样。当我将 WHERE 子句放在 EXISTS 中时,GROUP BY 存在问题。因为子句可能类似于WHERE Avis.Id=x,但 Id 是分组的,所以我不会得到正确的,或者我得到了所有,然后即使我要求 WHERE 子句总是正确的!=x
  • 您需要向我展示与您的示例数据相关的 EXISTS() 子句的真实示例,以便我了解它为什么不适合您。 Avis.Id=x 对我没有任何意义。我敢打赌,您没有将其与外部查询相关联。
【解决方案2】:

@Cato 是对的,遗憾的是我无法将其标记为正确答案,因为它只是一个评论。
我设法用“WITH”语句得到正确的结果。我首先在所有 4 个表上的组合 INNER JOIN 中过滤表,选择不想要的结果作为一种“黑名单”,并使用 LEFT JOIN 从 Tour 中选择不在 WITH 结果中的所有结果。
现在看起来像这样:

WITH partresult AS
(SELECT TourFk
 FROM Routesection r
 INNER JOIN Item i ON r.ItemFk=i.ID
 INNER JOIN Avis a ON a.ID=i.AvisFk
 INNER JOIN Tour t ON r.TourFk=t.ID
 WHERE (put some strange selections here ;)
        AND i.OemFk=5003)
SELECT t.ID, etc.
FROM Tour t
INNER JOIN Routesection r ON t.ID=r.TourFk
INNER JOIN Item i ON i.ID=r.ItemFk
INNER JOIN Avis a ON a.ID=i.AvisFk
LEFT JOIN partresult p ON t.ID=p.TourFk
WHERE p.TourFK IS NULL
      AND (nearly the same selections as above, so the server is a little bit faster)
GROUP BY t.ID, etc.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-29
    • 1970-01-01
    • 2013-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多