T-SQL - 子查询返回超过 1 个值

T-SQL - Subquery returned more than 1 value

有 2 个表:usersoffers

我需要为每个用户提取 3 个优惠。

我写了这个命令行:

SELECT TOP 10  
    sellerID, 
    Country, 
    (SELECT TOP 3 ItemID 
     FROM Items i 
     JOIN Sellers s ON s.sellerID = i.UserID 
     ORDER BY CreatedDate)
FROM 
    Sellers 
ORDER BY
    Country desc

不确定是否真的 returns 我在找什么,但我得到这个错误:

Subquery returned more than 1 value.
This is not permitted when the subquery follows =, !=, <, <= , > >, >= or when the subquery is used as an expression.`

可以提出解决方案或解决方法吗?

您在 select 子句中有子查询。那里必须 return 1 行。尝试加入它-

SELECT 
TOP 10  sellerID, 
Country, items.ItemID
from Sellers 
left join
(
   SELECT TOP 3 UserID, ItemID 
   from Items i 
   join Sellers s  
   on s.sellerID=i.UserID 
   order by CreatedDate
) items
on sellers.UserID = items.UserID
order by Country desc

眼前的问题是您要求 select 输出每行包含 sellerIdCountrythree 的值的行ItemID.

的值

子查询也与外部查询不相关,即您有对 Sellers table 的第二个引用,但没有执行任何操作来将值与外部查询匹配。

假设您实际上想要最多 10 个国家/地区中每个国家/地区的前 3 项,这应该很接近:

-- Sample data.
declare @Sellers as Table ( SellerId Int, Country VarChar(16) );
insert into @Sellers ( SellerId, Country ) values
  ( 1, 'Canada' ), ( 2, 'Italy' ), ( 3, 'Elbonia' ), ( 4, 'Maldives' ), ( 5, 'Fiji' ),
  ( 6, 'Ecuador' ), ( 7, 'Chile' ), ( 8, 'Mexico' ), ( 9, 'Palau' ), ( 10, 'Yap' ),
  ( 11, 'Saba' );
declare @Items as Table ( ItemId Int, UserId Int, CreatedDate Date );
insert into @Items ( ItemId, UserId, CreatedDate ) values
  ( 1, 3, '20150308' ), ( 2, 3, '20150619' ), ( 3, 3, '20120908' ), ( 4, 3, '20140228' ),
  ( 2, 9, '20150308' ), ( 3, 9, '20150619' ), ( 4, 9, '20120908' ), ( 5, 9, '20140228' ),
  ( 3, 6, '20150308' ), ( 4, 6, '20150619' ), ( 4, 6, '20120908' ), ( 6, 6, '20140228' );

select * from @Sellers;
select * from @Items;

-- Show the intermediate results.
with AllSellersAndItems as
  ( select S.SellerId, S.Country, I.ItemId,
    Row_Number() over ( partition by S.SellerId order by I.CreatedDate ) as ItemSequence,
    Dense_Rank() over ( order by Country ) as SellerSequence
    from @Sellers as S inner join
      @Items as I on I.UserId = S.SellerId )
  select * from AllSellersAndItems;

-- The real query.
with AllSellersAndItems as
  ( select S.SellerId, S.Country, I.ItemId,
    Row_Number() over ( partition by S.SellerId order by I.CreatedDate ) as ItemSequence,
    Dense_Rank() over ( order by Country ) as SellerSequence
    from @Sellers as S inner join
      @Items as I on I.UserId = S.SellerId )
  select SellerId, Country, ItemId, SellerSequence, ItemSequence
    from AllSellersAndItems
    where SellerSequence <= 10 and ItemSequence <= 3
    order by Country desc

此查询适合您:

    SELECT  TOP 10  sellerID,  Country, items.ItemID
    from Sellers 
    left join Items On Items.UserID = Sellers.sellerID
                   And Items.ItemID in ( Select Top 3 I_1.ItemID From Items As I_1
                                         Where I_1.UserID = Sellers.sellerID
                                         Order by CreatedDate )
   ORDER BY Country desc

CROSS APPLY 就是您所需要的。请看查询示例:

SELECT TOP (10) S.SellerID, S.Country, I.ItemID
FROM dbo.Sellers AS S
CROSS APPLY (
    SELECT TOP (3) I.ItemID
    FROM dbo.Items AS I
    WHERE S.SellerID = I.UserID
    ORDER BY I.CreatedDate
    ) AS I
ORDER BY S.Country DESC;

此查询将为您返回 TOP (10) 结果。如果您想获得 TOP (10) 个用户和每个用户 3 个项目(这意味着最多 30 条记录),请改用此查询:

SELECT S.SellerID, S.Country, I.ItemID
FROM (
    SELECT TOP (10) S.SellerID, S.Country
    FROM dbo.Sellers AS S
    ORDER BY S.Country DESC
    ) AS S
CROSS APPLY (
SELECT TOP (3) I.ItemID
FROM dbo.Items AS I
WHERE S.SellerID = I.UserID
ORDER BY I.CreatedDate
) AS I;

它的用途之一正是您所要求的。返回 TOP (n) 个子项。更多现实生活中的例子可以在这里找到:Real life example, when to use OUTER / CROSS APPLY in SQL