我有一个数据库,每天都会在其中创建一个新表并填充数据(我知道这并不理想,但我无法更改它)。每个表的格式为“TESTdata_xxxxx_DB”,其中xxxxx每天递增1。
我需要一种简单的方法来选择许多表(即多个日期)中的前 1000 行(满足特定条件的行)。例如,我需要跨表查询TESTdata_45800_DB,TESTdata_45801,...,TESTdata_45850_DB。
我尝试了以下查询,但显然添加“to”不起作用,并且用逗号分隔它们并不能按照我想要的方式组合它们:
SELECT TOP 1000
[ItemIndex],
[Data1],
[Data2],
[Data3]
FROM
[TESTDB1].[dbo].[TESTdata_45800_DB] (to...) [TESTdata_45850_DB]
WHERE
Data1 LIKE 'High' OR Data1 LIKE 'Medium'
ORDER BY
Data1
;
如有任何帮助,我们将不胜感激。
最佳答案
使用动态 SQL 的存储过程是解决此类问题的一个很酷的方法。在内存中创建一个数字表,使用它来创建您的 UNIONed super 表,然后执行动态 SQL 以获得您需要的结果:
CREATE PROCEDURE [dbo].[Top1000]
(
@startDatabaseNumber INT,
@endDatabaseNumber INT
)
AS
SET NOCOUNT ON
-- inspired by https://stackoverflow.com/a/33146869/7806251
DECLARE @digits TABLE(d INT)
INSERT INTO @digits
SELECT
d
FROM
(VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) v(d)
DECLARE @numbers TABLE(DatabaseNumber VARCHAR(5))
INSERT INTO @numbers
SELECT
LEFT('00000', 5 - LEN(n)) + n AS DatabaseNumber
FROM
(
SELECT
CAST(
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)
) AS VARCHAR(10)
) AS n
FROM
@digits ones,
@digits tens,
@digits hundreds,
@digits thousands,
@digits tenthousands
) x
WHERE
n BETWEEN @startDatabaseNumber AND @endDatabaseNumber
DECLARE @unionedTable VARCHAR(MAX) = (
SELECT
STRING_AGG(
CAST(
'(
SELECT
ItemIndex,
Data1,
Data2,
Data3
FROM
[TESTDB1].[dbo].[TESTdata_'+DatabaseNumber+'_DB]
)'
AS VARCHAR(MAX)) -- circumvents STRING_AGG() 8000 character constraint
, ' UNION ALL ') -- just UNION if you want to de-dupe
FROM
@numbers
)
DECLARE @sql NVARCHAR(MAX) = '
SELECT TOP 1000
*
FROM
('+@unionedTable+') UnionedTable
WHERE
Data1 IN (''High'', ''Medium'')
ORDER BY
Data1
;
'
-- PRINT @sql -- if you need to debug
EXECUTE sp_executesql @sql
一旦运行并存在,请使用您想要的任何开始和结束数字来调用它:
EXEC Top1000 5, 15;
最后,正如其他评论者所表达的那样,我建议不要每天创建一个新表如果你可以帮助它。将每天的数据插入到运行表中是更自然、更好的做法。
关于sql - 跨多个表选择 TOP 1000,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74167020/