重复查询而不是 UNION ALL 的更好方法?

Posted

技术标签:

【中文标题】重复查询而不是 UNION ALL 的更好方法?【英文标题】:Better way to repeat queries instead of UNION ALL? 【发布时间】:2015-10-28 22:47:31 【问题描述】:

我正在尝试创建一个可以多次输出特定行的查询。假设输出一行 6 次。我检查了与此相关的其他问题,但没有找到最能回答我问题的问题。 这是我的查询。

SELECT * FROM table WHERE id=1
UNION ALL
SELECT * FROM table WHERE id=1
UNION ALL
SELECT * FROM table WHERE id=1
UNION ALL
SELECT * FROM table WHERE id=1
UNION ALL
SELECT * FROM table WHERE id=1
UNION ALL
SELECT * FROM table WHERE id=1

此方法适用于少量重复。现在我的问题是,有没有更好(或标准)的方法来做这件事,这也适用于大量重复?

如果这个问题之前已经回答过,请放下链接,我会试一试。

我们将不胜感激。

【问题讨论】:

为什么要重复?如果你真的想要,那么将它们复制到一个表格中以供选择。 我想默认使用详细信息来填充 empty 插槽。如果它们达到 100 或 200,我真的必须复制它们吗?我的主要目标是在整个查询过程中保持相同的 ID。 发布您的示例表和预期结果。也许这可以澄清你的任务。 我需要这个的原因是因为我正在创建一个广告门户,它将有 6 个插槽(现在)。对于要在广告位中显示的横幅,它必须处于活动状态。我已经有一个将显示活动横幅的查询。我真正想做的是如果没有找到活动横幅或活动横幅不超过六个,则显示默认横幅。 这有点笨拙,但它可以满足您的需求。 sqlfiddle.com/#!9/c4328/1 老实说,您应该做的只是用另一种编程语言复制该行(无论您使用哪种编程语言来执行查询) 【参考方案1】:

执行此操作的方法是,无论您希望拥有多少行,您都可以制作一个数字表,您可以从中选择并通过您的 id + 您想要复制的行数加入。像这样

SELECT e.* 
FROM example e
JOIN
(   SELECT
        seq.s as digit
    FROM
    (   SELECT (hundreds.s + tens.s + ones.s) s
        FROM(SELECT 0  s UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) ones
        CROSS JOIN(SELECT 0 s UNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30 UNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60 UNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90) tens
        CROSS JOIN(SELECT 0 s UNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300 UNION ALL SELECT 400 UNION ALL SELECT 500 UNION ALL SELECT 600 UNION ALL SELECT 700 UNION ALL SELECT 800 UNION ALL SELECT 900) hundreds
    ) seq
) n ON e.id + 5 > n.digit
WHERE e.id = 1

FIDDLE

我之前发布的 sql fiddle(在 cmets 中)的问题是你必须在表中有足够的记录才能提取出准确的重复记录。这样你每次都会得到你想要的

注意:出于所有意图和目的,这是一个示例。我会强烈建议您不要一直运行此查询。如果你真的需要一个数字表然后创建一个并插入这些值一次。然后加入表。

如果你必须走这条路(在 mysql 中复制记录)那么这就是我会做的

CREATE TABLE digits (id INT);
INSERT INTO digits (id)
SELECT
    seq.s as digit
FROM
(   SELECT (hundreds.s + tens.s + ones.s) s
    FROM(SELECT 0  s UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) ones
    CROSS JOIN(SELECT 0 s UNION ALL SELECT 10 UNION ALL SELECT 20 UNION ALL SELECT 30 UNION ALL SELECT 40 UNION ALL SELECT 50 UNION ALL SELECT 60 UNION ALL SELECT 70 UNION ALL SELECT 80 UNION ALL SELECT 90) tens
    CROSS JOIN(SELECT 0 s UNION ALL SELECT 100 UNION ALL SELECT 200 UNION ALL SELECT 300 UNION ALL SELECT 400 UNION ALL SELECT 500 UNION ALL SELECT 600 UNION ALL SELECT 700 UNION ALL SELECT 800 UNION ALL SELECT 900) hundreds
) seq

既然你有一个数字表,就加入它

SELECT e.* 
FROM example e
JOIN digits d ON e.id + 5 < d.id
WHERE e.id = 1

【讨论】:

这是否意味着我将在mysql中有重复记录?如果是,我不认为我真的想这样做。这是交易:我有一个存储所有广告详细信息(id、标题、img_url、ad_url、状态)的表,并且我已经有一个函数可以查询数据库并获取状态为“活动”的广告,然后显示他们在广告位。我真正想要实现的是,如果一个或多个广告插槽为空(即如果广告已被停用),则获取默认横幅,该横幅也在数据库中,id=1。是否还需要创建重复记录? 就像我一直说的你应该用另一种编程语言来做这个【参考方案2】:

一次性创建一个包含大量 1-n 数字的表格,然后使用它“生成”为数字范围并加入该范围。

这是创建和填充表格的简单方法:

create table numbers (number int not null primary key auto_increment);
insert into numbers () values ();
insert into numbers select null from numbers;
insert into numbers select null from numbers;
insert into numbers select null from numbers;
insert into numbers select null from numbers;
insert into numbers select null from numbers;
insert into numbers select null from numbers;
insert into numbers select null from numbers;
insert into numbers select null from numbers;
insert into numbers select null from numbers;
insert into numbers select null from numbers;

此代码使用数字 1-1024 填充表格。 insert into numbers select null from numbers 每多执行一次,行数就会翻倍。

现在加入,说 100 次:

select table.* from table
join numbers on number <= 100
where id = 1

您当然可以将100 值参数化为查询参数,这意味着您可以通过一个查询来查询运行时需要多少行。

由于 mysql 不支持生成的序列,numbers 表可以非常方便地生成日期范围和所有类型的值。

【讨论】:

以上是关于重复查询而不是 UNION ALL 的更好方法?的主要内容,如果未能解决你的问题,请参考以下文章

mysql union和union all的区别

SQL Server-聚焦UNIOL ALL/UNION查询

根据 when 语句中的不同日期参数多次运行查询并合并结果,而不是多个 UNION ALL

Bigquery:根据不同的 date_trunc 多次运行查询并将结果合并,而不是多个 UNION ALL

UNION 与 UNION ALL 的性能

union 与 union all 的表现