SQL:放弃/返回不同的结果,如果行太多

发布于 2025-01-31 03:03:53 字数 477 浏览 4 评论 0原文

简短版本,我有一个SQL语句,其中仅想要结果如果返回的行数小于某些值(例如1000),否则我想要不同的结果集。当我只要把它们扔掉时,最好的做到这一点的方法是什么?

结果

SELECT * 
FROM T 
WHERE updated_at > timestamp 
  AND name <= 'Michael' 
ORDER BY name ASC

例如,我想返回提供最多有1000个条目

SELECT * 
FROM T 
ORDER BY name ASC 
LIMIT 25

的 询问只是扔掉它们。

(也很乐意使用Postgres扩展名,但更喜欢SQL)

-

要解释我在批处理客户要求的数据清新数据,有时客户需要知道他们已经收到的部分是否存在任何更改。但是,如果更改太多了,我只是放弃并开始从一开始就开始发送记录。

Short version, I have a SQL statement where I only want the results if the number of rows returned is less than some value (say 1000) and otherwise I want a different result set. What's the best way to do this without incurring the overhead of returning the 1000 rows (as would happen if I used limit) when I'm just going to throw them away?

For instance, I want to return the results of

SELECT * 
FROM T 
WHERE updated_at > timestamp 
  AND name <= 'Michael' 
ORDER BY name ASC

provided there are at most 1000 entries but if there are more than that I want to return

SELECT * 
FROM T 
ORDER BY name ASC 
LIMIT 25

Two queries isn't bad, but I definitely don't want to get 1000 records back from the first query only to toss them.

(Happy to use Postgres extensions too but prefer SQL)

--

To explain I'm refreshing data requested by client in batches and sometimes the client needs to know if there have been any changes in the part they've already received. If there are too many changes, however, I'm just giving up and starting to send the records from the start again.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

逆光飞翔i 2025-02-07 03:03:53
WITH max1000 AS (
   SELECT the_row, count(*) OVER () AS total
   FROM  (
      SELECT the_row  -- named row type
      FROM   T AS the_row
      WHERE  updated_at > timestamp
      AND    name <= 'Michael'
      ORDER  BY name
      LIMIT  1001
      ) sub
   )
SELECT (the_row).*  -- parentheses required
FROM   max1000 m
WHERE  total < 1001

UNION ALL
(  -- parentheses required
SELECT * 
FROM   T 
WHERE (SELECT total > 1000 FROM max1000 LIMIT 1)
ORDER  BY name
LIMIT  25
)

cte sub cte max1000在第一个查询中获得完整的,分类的结果 - 包裹为行类型工作。

外部选择添加总行计数。请参阅:

# 结果 - 如果其中少于1001。

外部的第二个 union 查询返回替代结果 - 如果需要超过1000

  • 。 .com/Question/59348755/组合-3-筛选态至输出1-table/59349080#59349080“>组合3个选择语句到输出1表

or:

WITH max1000 AS (
   SELECT *
   FROM   T
   WHERE  updated_at > timestamp
   AND    name <= 'Michael'
   ORDER  BY name
   LIMIT  1001
   )
, ct(ok) AS (SELECT count(*) < 1001 FROM max1000)   

SELECT *
FROM   max1000 m
WHERE (SELECT ok FROM ct)

UNION ALL
(  -- parentheses required
SELECT * 
FROM   T 
WHERE (SELECT NOT ok FROM ct)
ORDER  BY name
LIMIT  25
);

我认为我更喜欢2nd。不知道哪个更快。

在大多数调用中,要么优化少于1001行的性能。如果这是例外,我首先要经营一个便宜的计数。还取决于可用索引...

如果第一个查询发现没有行,您会得到无行。 (似乎是一个奇怪的结果。)

WITH max1000 AS (
   SELECT the_row, count(*) OVER () AS total
   FROM  (
      SELECT the_row  -- named row type
      FROM   T AS the_row
      WHERE  updated_at > timestamp
      AND    name <= 'Michael'
      ORDER  BY name
      LIMIT  1001
      ) sub
   )
SELECT (the_row).*  -- parentheses required
FROM   max1000 m
WHERE  total < 1001

UNION ALL
(  -- parentheses required
SELECT * 
FROM   T 
WHERE (SELECT total > 1000 FROM max1000 LIMIT 1)
ORDER  BY name
LIMIT  25
)

The subquery sub in CTE max1000 gets the complete, sorted result for the first query - wrapped as row type, and with LIMIT 1001 to avoid excess work.

The outer SELECT adds the total row count. See:

The first SELECT of the outer UNION query returns decomposed rows as result - if there are less than 1001 of them.

The second SELECT of the outer UNION query returns the alternate result - if there were more than 1000. Parentheses are required - see:

Or:

WITH max1000 AS (
   SELECT *
   FROM   T
   WHERE  updated_at > timestamp
   AND    name <= 'Michael'
   ORDER  BY name
   LIMIT  1001
   )
, ct(ok) AS (SELECT count(*) < 1001 FROM max1000)   

SELECT *
FROM   max1000 m
WHERE (SELECT ok FROM ct)

UNION ALL
(  -- parentheses required
SELECT * 
FROM   T 
WHERE (SELECT NOT ok FROM ct)
ORDER  BY name
LIMIT  25
);

I think I like the 2nd better. Not sure which is faster.

Either optimizes performance for less than 1001 rows in most calls. If that's the exception, I would first run a somewhat cheaper count. Also depends a lot on available indexes ...

You get no row if the first query finds no row. (Seems like an odd result.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文