从 SQL SELECT 语句中获取值,即使它在表中不存在

Posted

技术标签:

【中文标题】从 SQL SELECT 语句中获取值,即使它在表中不存在【英文标题】:Get value even if it doesn't exist in table from SQL SELECT statement 【发布时间】:2012-02-27 19:37:53 【问题描述】:

我有一个如下所示的 mysql 表:

|---ID---|---COUNTER---|
|   1    |      2      |
|   2    |      6      |
|   3    |      1      |
|   5    |      9      |
|   6    |      10     |

我正在寻找返回 ID 及其 COUNTER 的 SELECT 语句。该表只有 ID,例如:1、2、3、5、6。有没有你说的语句:我想要 ID 的 1 到 10,即使它们在表中不存在,如果 ID 不存在,则返回 ID 无论如何 COUNTER 值为 0。例如:

|---ID---|---COUNTER---|
|   1    |      2      |
|   2    |      6      |
|   3    |      1      |
|   4    |      0      |
|   5    |      9      |
|   6    |      10     |
|   7    |      0      |
|   8    |      0      |
|   9    |      0      |
|   10   |      0      |

我必须创建一个包含 NOT EXIST 参数的 SELECT 语句吗?

在此先感谢史蒂夫-O

【问题讨论】:

数据库不能返回一个不存在的ID,因为它不知道它应该返回。你有另一个表来定义什么是有效值吗? @Jan Hudec:不,我知道我没有一个是愚蠢的。但是,有什么方法可以通过 LEFT JOIN 实现我的目标吗? "我想要 ID 的 1 到 10" -- 1 到 10 的范围在哪里定义?例如在一张桌子上?作为参数传入? 我只是把它放在那里作为一个例子。感谢 Michal Powaga 解决方案,范围从最低 ID 到最高 【参考方案1】:

不创建临时表:

select t.num as id, coalesce(yt.counter, 0)
from your_table yt
right join (
    select 1 as num union select 2 union select 3 union select 4 union select 5 union
    select 6 union select 7 union select 8 union select 9 union select 10
) t on yt.id = t.num
order by t.num

还有更笼统的:

select t.num as id, coalesce(yt.counter, 0)
from your_table yt
right join (
    select t1.num + t2.num * 10 + t3.num * 100 as num
    from (
        select 1 as num union select 2 union select 3 union select 4 union select 5 union
        select 6 union select 7 union select 8 union select 9 union select 0
    ) t1
    cross join (
        select 1 as num union select 2 union select 3 union select 4 union select 5 union
        select 6 union select 7 union select 8 union select 9 union select 0
    ) t2
    cross join (
        select 1 as num union select 2 union select 3 union select 4 union select 5 union
        select 6 union select 7 union select 8 union select 9 union select 0
    ) t3
) t on yt.id = t.num
where t.num between (select min(id) from your_table) and (select max(id) from your_table)

您可以在这里自己定义限制我使用了minmaxid 值来自your_table

【讨论】:

我也应该用我的表名替换“y”和“yt”吗? @Steve-O yt 只是一个别名,因此您可以保持原样(如果您不喜欢它,也可以更改)。只有your_table 更改为正确的表名,如果列正确,这应该没问题。【参考方案2】:

它不是很健壮,但是如果您创建了一个包含所需 ID 的临时表,则可以将连接保留到包含 ID 和 Counter 的表中,其中将包含所有值:

Declare @tempidtable as table ( imaginaryid int )

insert into @tempidtable ( imaginaryid ) values ( 1 )
insert into @tempidtable ( imaginaryid ) values ( 2 )
insert into @tempidtable ( imaginaryid ) values ( 3 )

select 
@temptable.imaginaryid,
ISNULL(yourothertable.counter, 0)
from @tempidtable
left join yourothertable
on @tempidtable.imaginaryid = yourothertable.id

正如 Tomek 所说,您可以遍历插入以使其更易于维护,或者可能将您想要的 id 作为基础存储在另一个表中,使用它作为连接而不是临时表的基础。

【讨论】:

【参考方案3】:

创建一个包含所有可能 ID 的表:

create table Numbers (nr int primary key);

declare i int default 1;

while i < 100000 do
    insert into Numbers (nr) values (i);
    set i = i + 1;
end while;

然后你可以使用left join返回所有数字:

select  n.NR
,       c.Counter
from    Numbers n
left join
        Counters c
on      c.ID = n.NR

【讨论】:

【参考方案4】:

您可以使用left join 来解决您的问题。阅读更多关于left joinhere

【讨论】:

在sql中做同样的事情有不同的方法,我给出了一种方法。 -1 :否决者请发表评论。如果@onedaywhen 你已经完成了,请告诉我这个答案是否不正确。 我没有说“应该”,“将”是建议,“应该”是强制性的。无论如何更新了我的答案。【参考方案5】:

我认为您必须使用从 1 到 N 的完整数字序列创建(在循环中生成)临时表(其中 N 是计数表的 MAX(Id))。然后对该表进行左连接并应用 GROUP BY 子句。

【讨论】:

【参考方案6】:

您需要整数范围才能根据 ID 与您的表进行外部联接。如果您不想使用临时表,则生成整数范围取决于 SQL 供应商。有关如何根据您的 SQL 供应商执行此操作的提示,请参阅 SQL SELECT to get the first N positive integers。

【讨论】:

以上是关于从 SQL SELECT 语句中获取值,即使它在表中不存在的主要内容,如果未能解决你的问题,请参考以下文章

sql查询总结

sql查询总结

sql语句获取表中最新数据

SQL select语句汇总几种情况并返回百分比?

使用 select 语句在表值函数中传递参数

SQL动态SELECT语句来自存储在表中的值