【问题标题】:Exclude rows from a SQL query based on number of rows an ID is present in根据 ID 所在的行数从 SQL 查询中排除行
【发布时间】:2016-10-07 14:35:26
【问题描述】:

我早些时候提取了一些数据,发现我的结果太多而无用(返回超过 400 万行)。我发现罪魁祸首是一大堆 ID,每个 ID 都有几千条记录。

这是数据的结构。我有两张桌子。 tbl1 对每个“ATID”都有一条记录(基本上,ATID 是一个比例 ID)。但是,每个 ATID 本质上都是它自己的表 - 它对秤上的每个项目都有记录。 tbl2 枚举这些项目 - 每个 ATID 的每个比例项目都有一行。所以它对于每个 ATID 都有 1 到 500,000 行(我知道,非常过分)。

我想排除超过 100 行的 ATID。仅供参考,这是我拥有只读权限的数据库。

这是我的原始查询:

SELECT tbl1.ATID, tbl1.ATDesc, tbl2.AValue, tbl2.ADesc, tbl2.APosNeg
FROM tbl1 LEFT OUTER JOIN tbl2 ON (tb1.ATID = tbl2.ATID);

这是我用来获取每个 ATID 的 ATID 列表和 tbl2 中记录计数的查询:

select ATID, count(*) as row_count
from tbl2
group by ATID
order by row_count desc;

对于我的最终产品,我只想返回 tbl2 中少于 100 行的 ATID。但是,如果我什至尝试使用 row_count 变量将 WHERE 子句添加到第二个查询,它就会失败。所以我不知道如何将这两个查询结合起来并获得 WHERE 子句。

我唯一的选择是在我知道 ATID 有太多记录但要排除的记录太多时专门排除 ATID(即,使用 WHERE NOT ATID = 1016 AND NOT ATID = 554 AND NOT .... 等)

【问题讨论】:

  • 你知道怎么做子查询吗?

标签: sql sql-server select count


【解决方案1】:

您已经完成了,您只需将两个查询放在一起:

SELECT tbl1.ATID, tbl1.ATDesc, tbl2.AValue, tbl2.ADesc, tbl2.APosNeg
FROM tbl1 LEFT OUTER JOIN tbl2 ON (tb1.ATID = tbl2.ATID)
WHERE tbl1.ATID NOT IN (
  select ATID
  from tbl2
  group by ATID
  HAVING COUNT(*) >= 100
)

【讨论】:

    【解决方案2】:

    这是使用

    的一种方法

    Count() Over()窗口聚合将counttbl2表中每个ATID的记录数。然后计数可以用来过滤Join条件中的ATID

    SELECT tbl1.ATID,
           tbl1.ATDesc,
           tbl2.AValue,
           tbl2.ADesc,
           tbl2.APosNeg
    FROM   tbl1
           LEFT OUTER JOIN (SELECT Count(1)OVER(partition BY ATID) AS cnt,*
                            FROM   tbl2) tbl2
                        ON tb1.ATID = tbl2.ATID
                           AND tbl2.cnt <= 100; 
    

    注意:如果您不想要来自tabl1 的所有ATID's,则将tbl2.cnt &lt;= 100 条件移动到Where 子句,这样您将获得ATID's 的计数,其计数为小于100 in tbl2

    【讨论】:

      【解决方案3】:

      对于 SQL 服务器,使用 CTE(比子查询更快)。此外,查询中不必要的括号

      with RowCo as
      (
      select ATID, count(*) as row_count
      from tbl2
      group by ATID
      having row_count <= 100
      )
      
      SELECT tbl1.ATID, tbl1.ATDesc, tbl2.AValue, tbl2.ADesc, tbl2.APosNeg
      FROM tbl1 
      inner join RowCo
          on RowCo.ATID = tbl1.ATID
      LEFT JOIN tbl2 
          ON tb1.ATID = tbl2.ATID
      

      【讨论】:

      • 谢谢 - 是什么让 CTE 比子查询更快?
      【解决方案4】:

      对于第二个查询,与聚合函数相关的过滤器位于 HAVING 部分

      select ATID, count(*) as row_count
      from tbl2
      group by ATID
      order by row_count desc;
      having count(*) < 100
      

      对于第一个查询,您可以简单地使用子查询

      SELECT tbl1.ATID, tbl1.ATDesc, tbl2.AValue, tbl2.ADesc, tbl2.APosNeg
      FROM tbl1 
           LEFT OUTER JOIN tbl2 ON (tb1.ATID = tbl2.ATID)
      WHERE tbl1.ATID in (select ATID
                          from tbl2
                          group by ATID
                          having count(*) < 100)
      

      【讨论】:

        猜你喜欢
        • 2020-11-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多