从 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)
您可以在这里自己定义限制我使用了min
和max
的id
值来自your_table
。
【讨论】:
我也应该用我的表名替换“y”和“yt”吗? @Steve-Oyt
只是一个别名,因此您可以保持原样(如果您不喜欢它,也可以更改)。只有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 join
here
【讨论】:
在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 语句中获取值,即使它在表中不存在的主要内容,如果未能解决你的问题,请参考以下文章