【问题标题】:Alternative to nested select statements替代嵌套选择语句
【发布时间】:2013-09-24 18:17:06
【问题描述】:

我有以下表格结构:

目前过滤用户是通过非常复杂的嵌套 SQL 查询实现的(而且它是由 Linq 自动生成的)。我看起来大概是这样的:

SELECT FROM (SELECT FROM (SELECT FROM ( infinity here...))))

有没有简化过滤过程的好方法?

请注意有不同的特征类型。以下是子查询条件示例:

... WHERE cv.Text like '%aaa%' AND c.Id = 5
... WHERE cv.ImageId IS NOT NULL AND c.Id = 10
... WHERE cv.Number > 5 AND c.Id = 33

等等……

将不胜感激任何帮助和想法(更改数据库结构、更改技术等...),谢谢!

【问题讨论】:

  • 如果它是由 LINQ 生成的,那么你为什么要关心它是否看起来很复杂呢?数据库应该是 3NF,它看起来是。您可能在 ImageId 和 AllowedValueId 上缺少 FK。
  • 有 FK,我只是没有将它们添加到 DB 图中以简化视图。实际上,我并不是 100% 信任 LINQ,而且我认为自动生成的 SQL 脚本(稍后会被“执行”)远未达到最佳性能。也许一些 DB 视图或存储过程会提供更好的结果。
  • 您的LINQ 查询在哪里?
  • 你的问题很难说我们如何改进它。我认为你应该指定你想如何过滤用户,最后你想得到什么。
  • 最终我会对用户 ID 感到满意。现在linq查询是由多种类型生成的,最后看起来像: users.Where(/*condition*/).Where(/*condition*/).Where(/*condition*/).Where(/*condition */) 等等...

标签: sql sql-server linq tsql


【解决方案1】:

正如你描述的那样,你的查询应该是这样的

select u.id
from Users as u
where
    exists (
        select *
        from CharacteristicValues as cv
        where cv.Text like '%aaa%' and cv.CharacteristicId = 5 and u.Id = cv.UserId
    ) and 
    exists (
        select *
        from CharacteristicValues as cv
        where cv.ImageId is not null and cv.CharacteristicId = 10 and u.Id = cv.UserId
    ) and 
    exists (
        select *
        from CharacteristicValues as cv
        where cv.Number > 5 and cv.CharacteristicId = 33 and u.Id = cv.UserId
    )

甚至

    select distinct cv.UserId
    from CharacteristicValues as cv
    where cv.Text like '%aaa%' and cv.CharacteristicId = 5

    union

    select distinct cv.UserId
    from CharacteristicValues as cv
    where cv.ImageId is not null and cv.CharacteristicId = 10

    union

    select distinct cv.UserId
    from CharacteristicValues as cv
    where cv.Number > 5 and cv.CharacteristicId = 33

【讨论】:

  • 在这种方法中也有许多“SELECT”语句。我在考虑“类似枢轴”的方法。生成一些带有列的 tmp 表/视图:UserId、Characteristic1Value、Characteristic2Value、Ch-c3Val、C4V、... CnV。如果我有这样的表,那么我将能够运行具有以下条件的单个“SELECT”:WHERE C1V = 5 AND C7V IS NOT NULL AND C37 > 3 AND C88 LIKE '%Bob%'。我考虑使用 'pivot' SQL 关键字或 OLAP 方法。但另一个问题是可能会有 2-5K+ 特征和 100K+ 用户。
  • 我正在分析 TFS 数据库结构。它具有与我的 DB 相似的结构。这是相关性:WorkItem User;字段 特征;字段值 特征值。 TFS 支持添加新字段,并且它有自己的 WIQL(工作项查询语言)。我分析了查询,发现它是针对包含所有字段的列的聚合视图运行的。但这种方法不太可能不适用于我的情况。普通的 MSSQL 表只能有 1024 列。当然我可以使用宽表...但是解决方案会有点复杂。
【解决方案2】:

SQL to LINQ 的表现会很差
如果你想优化性能和可扩展性,那就去 TSQL

  1. 数据库设计 3nf
  2. 索引
    并且不要过度索引,因为它们会减慢插入和更新速度
  3. 查询设计
  4. 本地缓存

本地缓存
在 exe 开始时下载静态或半静态 FK 表并将它们保存在字典中。
然后在您的下拉菜单中使用字典而不是另一个对 SQL 的调用。
然后在查询中我发送 FK ID,这样选择就少了一个连接(它会有所不同)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-28
    • 2017-09-15
    • 2021-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多