SQL Server SQL服务器错误:子查询返回了多个值

bd1hkmkf  于 2023-02-03  发布在  其他
关注(0)|答案(6)|浏览(152)

我正在运行一个查询,并尝试将2016年的访问量计入一个存储桶,将2017年的访问量计入另一个存储桶。代码如下所示,但我不确定为什么会出现错误:
子查询返回了多个值。当子查询跟在=、!=、〈等后面或子查询用作表达式时,不允许出现这种情况。
任何帮助或建议如何去做这将是非常感谢。谢谢。

select distinct 
    person.personid, 
    person.DOB,
    person.FullName, 
    (select sum(events) 
     from Visit 
     where date between 20170101 and 20171231 
     group by PersonID) as visit2017, 
    (select sum(events) 
     from Visit 
     where date between 20160101 and 20161231 
     group by PersonID) as visit2016
into 
    #temp
from 
    table1 person 
left join 
    table2 visit on person.personid = visit.personid
where 
    visit.date between 20160101 AND 20171231 ;
1szpjjfi

1szpjjfi1#

你忘了将子查询限制在当前的人,但是,如果这是我的选择,我会用CTE写它,并加入它:

with visit2017 as 
   (select sum(events) as sum_events, PersonID
    from Visit 
    where date between 20170101 and 20171231 
    group by PersonID ), 
visit2016 as
   (select sum(events) as sum_events, PersonID 
    from Visit 
    where date between 20160101 and 20161231 
    group by PersonID ) 
select distinct 
       person.personid, 
       person.DOB,
       person.FullName, 
       visit2017.sum_events as visit2017,
       visit2016.sum_events as visit2016
into #temp
from table1 person 
left join table2 visit --< I don't understand this joing
on person.personid=visit.personid
left join visit2017 
on person.personid=visit2017.personid    --< important
left join visit2016
on person.personid=visit2016.personid    --< important
where visit.date between 20160101 AND 20171231 ;
tf7tbtn2

tf7tbtn22#

在子查询和外部查询中使用别名并添加where子句。

SELECT PersonID,
       ( SELECT sum(events) from Visit AS V where date between 20170101 and   
         T.PersonID = V.PersonID ) AS VV
FROM TableA AS T
pjngdqdw

pjngdqdw3#

从您的查询看,它如下所示:

select sum(events) from Visit where date between 20170101 and 20171231 group by PersonID

可以返回多个记录,因为它为每个personID返回总和(事件)。请尝试单独运行此程序,以查看它是否返回多个结果

wwtsj6pe

wwtsj6pe4#

出现该错误的原因是子查询希望返回1个结果,但查询生成了多行。您可以自行运行子查询以确认错误。
您可以将子查询重构为连接

select distinct 
person.personid, 
peron.DOB,
person.FullName, 
sum(visit.events) AS visit2017, 
sum(visit2.events) AS visit2016

into #temp
from table1 person 
left join table2 visit
    on person.personid=visit.personid
    AND date between 20170101 and 20171231
left join table2 visit2
    on person.personid=visit2.personid
    AND date between 20160101 and 20161231
where (visit.date between 20170101 and 20171231
OR visit2.date between 20160101 and 20161231) 
GROUP BY    
person.personid, 
peron.DOB,
person.FullName;
ztmd8pv5

ztmd8pv55#

当你这样做的时候,通常最好是在一次选择中计算所有的年份,这样就不必多次读取表,而且如果你使用cross apply,你也不需要将结果乘以所有的事件,也不需要使用distinct。

select 
    person.personid, 
    person.DOB,
    person.FullName,
    visit.visit_2017,
    visit.visit_2018
into 
    #temp
from 
    table1 person
    cross apply (
        select 
            sum(case when date >= '20170101' and date < '20180101' then events end) as visit_2017,
            sum(case when date >= '20160101' and date < '20170101' then events end) as visit_2016
         from 
             Visit 
         where
             date >= '20160101' and date < '20180101' and 
             Visit.PersonID = person.PersonID
    ) visit

它看起来要复杂得多,但并不难学,Case inside a sum通常很有用,使用outer apply你可以从同一个查询中得到多个结果,并将其放入最终的select中,这与select部分中的(select..)不同。
我还将between改成了两个独立的〉=和〈。Between在使用日期时可以正常工作,但如果是datetime/smalldatetime等,那么在时间不是00:00的最后一天,您将错过任何内容

cig3rfwq

cig3rfwq6#

我假设这里有一个表Visit,其中Date、PersonID是字段,还有一个表person,其中personid、DOB和FullName是字段。

select person.personid,
       person.dob,
       person.fullname,
       Count(Year(visit.date))
from   person p
       join visit v
         on p.personid = v.personid
where  Year(visit.date) in ( 2016, 2017 )
group  by p.personid,
          p.dob,
          p.fullname,
          Year(visit.date)

这将计算每年的访问次数

相关问题