从子查询返回多个聚合列

时间:2021-02-21 18:22:00

标签: sql sql-server tsql

我正在尝试通过聚合另一个表中的一些行来扩展现有查询。 当我只返回这样的一列时它有效:

Select DISTINCT 
   Contracts.id, 
   Contracts.beginTime, 
   Contracts.endTime, 
   Suppliers.name
   (SELECT COUNT(p.id) from production as p where p.id_contract = Contracts.id)
FROM Contracts 
LEFT JOIN Suppliers on Contracts.id = Suppliers.id_contract

然后我尝试为聚合卷添加另一列:

Select DISTINCT 
   Contracts.id, 
   Contracts.beginTime, 
   Contracts.endTime, 
   Suppliers.name
   (SELECT COUNT(p.id), SUM(p.volume) from production as p where p.id_contract = Contracts.id)
FROM Contracts 
LEFT JOIN Suppliers on Contracts.id = Suppliers.id_contract

但是,这会返回以下错误:

<块引用>

当子查询没有用EXISTS引入时,select列表中只能指定一个表达式。

我对 EXISTS 关键字进行了一些试验,但不知道如何使它起作用。此外,我不确定这是否适合我的情况。

所需的输出如下:

contract1Id, supplierInfoContract1, nrItemsContract1, sumVolumeContract1
contract2Id, supplierInfoContract2, nrItemsContract2, sumVolumeContract2

4 个答案:

答案 0 :(得分:3)

不使用 DISTINCT 和子查询,使用 GROUP BY 和普通连接来获取聚合。并且始终使用别名,它会让您的生活更轻松:

SELECT
    c.id,
    c.beginTime,
    c.endTime,
    s.name,
    COUNT(p.id) prod_count,
    SUM(p.volume) prod_vol
FROM Contracts c
LEFT JOIN production p on p.id_contract = c.id
LEFT JOIN Suppliers s on c.id = s.id_contract
GROUP BY c.id, c.beginTime, c.endTime, s.name;

另一种选择是APPLY分组子查询

SELECT DISTINCT
    c.id,
    c.beginTime,
    c.endTime,
    s.name,
    p.prod_count,
    p.prod_vol
FROM Contracts c
LEFT JOIN Suppliers s on c.id = s.id_contract
OUTER APPLY (
    SELECT
        COUNT(p.id) prod_count,
        SUM(p.volume) prod_vol
    FROM production p WHERE p.id_contract = c.id
    GROUP BY ()
) p;

您也可以使用 CROSS APPLY 并省略 GROUP BY ()this uses a scalar aggregate 并返回 0 而不是 null 表示没有行。

最后一点:连接查询中的 DISTINCTa bit of a code smell,这通常表明查询编写者没有认真考虑连接表返回的内容,并且只是想摆脱重复的行。

答案 1 :(得分:0)

你应该像下面这样使用它:

Select DISTINCT Contracts.id, Contracts.beginTime, Contracts.endTime, Suppliers.name
(SELECT COUNT(p.id) from production as p where p.id_contract = Contracts.id) as CNT,
(SELECT SUM(p.volume) from production as p where p.id_contract = Contracts.id) as VOLUME
FROM Contracts 
LEFT JOIN Suppliers on Contracts.id = Suppliers.id_contract

答案 2 :(得分:0)

我想您可以尝试将查询改写为

 SELECT X.ID,X.beginTime,X.endTime,X.name,CR.CNTT,CR.TOTAL_VOLUME
 FROM
 (
     Select DISTINCT Contracts.id, Contracts.beginTime, Contracts.endTime,      Suppliers.name
     FROM Contracts 
     LEFT JOIN Suppliers on Contracts.id = Suppliers.id_contract
 )X
 CROSS APPLY
 (
   SELECT COUNT(p.id)AS CNTT,SUM(p.volume) AS TOTAL_VOLUME
   from production as p where p.id_contract = X.id
 )CR

答案 3 :(得分:0)

我通过分离子查询稍微修改了你的查询。

Select DISTINCT 
   Contracts.id, 
   Contracts.beginTime, 
   Contracts.endTime, 
   Suppliers.name,
   (SELECT COUNT(p.id) from production as p where p.id_contract = Contracts.id) count_id,
    (SELECT SUM(p.volume) from production as p where p.id_contract = Contracts.id) sum_volume
FROM Contracts 
LEFT JOIN Suppliers on Contracts.id = Suppliers.id_contract