Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql &引用;子查询返回了多个值“1”;对于选择子查询_Sql_Sql Server_Sql Server 2008_Subquery - Fatal编程技术网

Sql &引用;子查询返回了多个值“1”;对于选择子查询

Sql &引用;子查询返回了多个值“1”;对于选择子查询,sql,sql-server,sql-server-2008,subquery,Sql,Sql Server,Sql Server 2008,Subquery,我正在使用MS SQL Server Management Studio 2008。我在编写子查询时遇到问题。这是整个查询,如下所示: SELECT DISTINCT FH.ShipDate, AVG(FH.[Dist Freight]) AS [Atlantic Freight Charge], (SELECT DISTINCT [Non-Atlantic Freight Charge] FROM (SELECT DISTINCT

我正在使用MS SQL Server Management Studio 2008。我在编写子查询时遇到问题。这是整个查询,如下所示:

SELECT DISTINCT 
    FH.ShipDate, AVG(FH.[Dist Freight]) AS [Atlantic Freight Charge], 
    (SELECT DISTINCT [Non-Atlantic Freight Charge]
     FROM 
         (SELECT DISTINCT 
              FH.ShipDate, AVG(FH.[Dist Freight]) AS [Non-Atlantic Freight Charge]
          FROM dbo.vw_FreightHistory AS FH
          WHERE VendorName != 'Atlantic Trucking'
          GROUP BY ShipDate, VendorName) AS [Non-Atlantic Freight Charge])
FROM dbo.vw_FreightHistory as FH
WHERE VendorName = 'Atlantic Trucking'
GROUP BY ShipDate, VendorName
ORDER BY ShipDate
当我添加第二个子查询时,问题首先出现了。第一个子查询没有返回任何错误,但它显示了每个ShipDate记录中“Dist运费”的全部平均值,而不是仅该ShipDate的平均值。我编写了第二个子查询以尝试修复该问题,但现在我遇到了以下错误:

Msg 512,第16级,状态1,第1行
子查询返回了多个值。当子查询在=、!=、=或者当子查询用作表达式时


如果我需要澄清什么,请告诉我。

这取决于如果返回多行,您希望在单个列中显示什么

如果需要费用总额,请在多行返回子查询周围使用
SUM()

SELECT DISTINCT FH.ShipDate, AVG(FH.[Dist Freight]) AS [Atlantic Freight Charge], 
SUM(SELECT DISTINCT [Non-Atlantic Freight Charge]
  FROM 
    (SELECT DISTINCT FH.ShipDate, AVG(FH.[Dist Freight]) AS [Non-Atlantic Freight Charge]
        FROM dbo.vw_FreightHistory AS FH
        WHERE VendorName != 'Atlantic Trucking'
        GROUP BY ShipDate, VendorName) AS [Non-Atlantic Freight Charge]))
FROM dbo.vw_FreightHistory as FH
WHERE VendorName = 'Atlantic Trucking'
GROUP BY ShipDate, VendorName
ORDER BY ShipDate

我想你想要的是这样的:

 SELECT 
    FH.ShipDate, 
    AVG(CASE 
           WHEN VendorName = 'Atlantic Trucking' 
           THEN FH.[Dist Freight] 
           ELSE NULL 
        END) AS [Atlantic Freight Charge],  
    AVG(CASE 
           WHEN VendorName != 'Atlantic Trucking' 
           THEN FH.[Dist Freight] 
           ELSE NULL 
         END) AS [Non-Atlantic Freight Charge]
FROM 
    dbo.vw_FreightHistory as FH
GROUP BY 
    ShipDate
ORDER BY 
    ShipDate
ShipDate        Atlantic Freight Charge | FULL OUTER JOIN |  ShipDate        Non-Atlantic Freight Charge
01/01/2012      1.00                    |                 |  NULL            NULL
01/02/2012      1.00                    |                 |  NULL            NULL
01/03/2012      1.00                    |                 |  NULL            NULL
01/04/2012      1.00                    |                 |  01/03/2012      2.00
01/05/2012      1.00                    |                 |  01/04/2012      3.00
NULL            NULL                    |                 |  01/05/2012      4.00
NULL            NULL                    |                 |  01/06/2012      5.00
NULL            NULL                    |                 |  01/07/2012      6.00
ShipDate        Atlantic Freight Charge  Non-Atlantic Freight Charge
01/01/2012      1.00                     0.00
01/02/2012      1.00                     0.00
01/03/2012      1.00                     0.00
01/04/2012      1.00                     2.00
01/05/2012      1.00                     3.00
01/05/2012      0.00                     4.00
01/06/2012      0.00                     5.00
01/07/2012      0.00                     6.00

问题是您有一个子查询返回多行,并且您试图将其作为值存储在单个行/列组合中

为了理解为什么会出现这种情况,让我们看看外部查询“大西洋运费”的结果是什么:

表1-大西洋运费 让我们看看内部子查询可能返回什么:

表2-非大西洋运费 最后,表2中不同的
非大西洋运费
行是什么样子的

表3-不同的非大西洋运费 现在,在SQL中,您需要根据SELECT子句指定一个包含三列的报告。下面是它的布局:

SELECT DISTINCT 

  FH.ShipDate

, AVG(FH.[Dist Freight]) AS [Atlantic Freight Charge]

, (SELECT DISTINCT [Non-Atlantic Freight Charge]
    FROM 
      (SELECT DISTINCT FH.ShipDate, AVG(FH.[Dist Freight]) AS [Non-Atlantic Freight Charge]
          FROM dbo.vw_FreightHistory AS FH
          WHERE VendorName != 'Atlantic Trucking'
          GROUP BY ShipDate, VendorName) AS [Non-Atlantic Freight Charge])
您可以看到第一列是
ShipDate
,第二列是
大西洋运费
,第三列是从内部子查询中查询每个不同的
非大西洋运费

为了使SQLServer能够正确地表示这一点,请设想尝试将该查询的结果放在第一个表中

因此,对于表1的第一行:

ShipDate        Atlantic Freight Charge
01/01/2012      1.00
我们需要添加一列
非大西洋运费
,并需要在其中存储表3中的查询结果:

| ShipDate      | Atlantic Freight Charge | Non-Atlantic Freight Charge     |
|---------------|-------------------------|---------------------------------|
| 01/01/2012    | 1.00                    | | Non-Atlantic Freight Charge | |
|               |                         | |-----------------------------| |
|               |                         | | 2.00                        | |
|               |                         | | 3.00                        | |
|               |                         | | 4.00                        | |
|               |                         | | 5.00                        | |
|               |                         | | 6.00                        | |
|               |                         | |-----------------------------| |
|---------------------------------------------------------------------------|
哦。我们的桌子里面有一张桌子

这就是问题所在,我们有一张桌子在另一张桌子里面

因此,您的问题有两种解决方案。你应该评估每一种方法的性能

第一个是使用一个名为的功能运行两个单独的查询并连接结果

该查询如下所示:

 SELECT 
    FH.ShipDate, 
    AVG(CASE 
           WHEN VendorName = 'Atlantic Trucking' 
           THEN FH.[Dist Freight] 
           ELSE NULL 
        END) AS [Atlantic Freight Charge],  
    AVG(CASE 
           WHEN VendorName != 'Atlantic Trucking' 
           THEN FH.[Dist Freight] 
           ELSE NULL 
         END) AS [Non-Atlantic Freight Charge]
FROM 
    dbo.vw_FreightHistory as FH
GROUP BY 
    ShipDate
ORDER BY 
    ShipDate
ShipDate        Atlantic Freight Charge | FULL OUTER JOIN |  ShipDate        Non-Atlantic Freight Charge
01/01/2012      1.00                    |                 |  NULL            NULL
01/02/2012      1.00                    |                 |  NULL            NULL
01/03/2012      1.00                    |                 |  NULL            NULL
01/04/2012      1.00                    |                 |  01/03/2012      2.00
01/05/2012      1.00                    |                 |  01/04/2012      3.00
NULL            NULL                    |                 |  01/05/2012      4.00
NULL            NULL                    |                 |  01/06/2012      5.00
NULL            NULL                    |                 |  01/07/2012      6.00
ShipDate        Atlantic Freight Charge  Non-Atlantic Freight Charge
01/01/2012      1.00                     0.00
01/02/2012      1.00                     0.00
01/03/2012      1.00                     0.00
01/04/2012      1.00                     2.00
01/05/2012      1.00                     3.00
01/05/2012      0.00                     4.00
01/06/2012      0.00                     5.00
01/07/2012      0.00                     6.00
CTE溶液 我做了一些改变,需要指出:

  • 我删除了“Order By”,一般来说,订购应该由任何正在使用SQL Server数据的人来完成,当您的客户端应用程序也可以这样做时,不要要求服务器订购一些东西,从而对服务器造成不必要的负担
  • 无论如何,
    orderby
    实际上在公共表表达式中是被禁止的,所以我必须将该子句移到末尾
  • 我已经将您的查询分为两部分,Atlantic和NonAtlantic,并使用
    完全外部联接来连接它们,因此一行中缺少的任何一行仍将显示,但它将显示为零。确保这是你想要的
  • 我使用
    COALESCE
    来确保如果有一天没有
    Atlantic运费
    s,因此在
    Atlantic
    CTE中没有对应于该天的发货日期,那么它将使用来自
    非大西洋
    CTE的日期 其工作方式是将两个查询连接起来,如下所示:

     SELECT 
        FH.ShipDate, 
        AVG(CASE 
               WHEN VendorName = 'Atlantic Trucking' 
               THEN FH.[Dist Freight] 
               ELSE NULL 
            END) AS [Atlantic Freight Charge],  
        AVG(CASE 
               WHEN VendorName != 'Atlantic Trucking' 
               THEN FH.[Dist Freight] 
               ELSE NULL 
             END) AS [Non-Atlantic Freight Charge]
    FROM 
        dbo.vw_FreightHistory as FH
    GROUP BY 
        ShipDate
    ORDER BY 
        ShipDate
    
    ShipDate        Atlantic Freight Charge | FULL OUTER JOIN |  ShipDate        Non-Atlantic Freight Charge
    01/01/2012      1.00                    |                 |  NULL            NULL
    01/02/2012      1.00                    |                 |  NULL            NULL
    01/03/2012      1.00                    |                 |  NULL            NULL
    01/04/2012      1.00                    |                 |  01/03/2012      2.00
    01/05/2012      1.00                    |                 |  01/04/2012      3.00
    NULL            NULL                    |                 |  01/05/2012      4.00
    NULL            NULL                    |                 |  01/06/2012      5.00
    NULL            NULL                    |                 |  01/07/2012      6.00
    
    ShipDate        Atlantic Freight Charge  Non-Atlantic Freight Charge
    01/01/2012      1.00                     0.00
    01/02/2012      1.00                     0.00
    01/03/2012      1.00                     0.00
    01/04/2012      1.00                     2.00
    01/05/2012      1.00                     3.00
    01/05/2012      0.00                     4.00
    01/06/2012      0.00                     5.00
    01/07/2012      0.00                     6.00
    
    因此,
    COALESCE
    ISNULL
    允许我将其转换为一组数据,如下所示:

     SELECT 
        FH.ShipDate, 
        AVG(CASE 
               WHEN VendorName = 'Atlantic Trucking' 
               THEN FH.[Dist Freight] 
               ELSE NULL 
            END) AS [Atlantic Freight Charge],  
        AVG(CASE 
               WHEN VendorName != 'Atlantic Trucking' 
               THEN FH.[Dist Freight] 
               ELSE NULL 
             END) AS [Non-Atlantic Freight Charge]
    FROM 
        dbo.vw_FreightHistory as FH
    GROUP BY 
        ShipDate
    ORDER BY 
        ShipDate
    
    ShipDate        Atlantic Freight Charge | FULL OUTER JOIN |  ShipDate        Non-Atlantic Freight Charge
    01/01/2012      1.00                    |                 |  NULL            NULL
    01/02/2012      1.00                    |                 |  NULL            NULL
    01/03/2012      1.00                    |                 |  NULL            NULL
    01/04/2012      1.00                    |                 |  01/03/2012      2.00
    01/05/2012      1.00                    |                 |  01/04/2012      3.00
    NULL            NULL                    |                 |  01/05/2012      4.00
    NULL            NULL                    |                 |  01/06/2012      5.00
    NULL            NULL                    |                 |  01/07/2012      6.00
    
    ShipDate        Atlantic Freight Charge  Non-Atlantic Freight Charge
    01/01/2012      1.00                     0.00
    01/02/2012      1.00                     0.00
    01/03/2012      1.00                     0.00
    01/04/2012      1.00                     2.00
    01/05/2012      1.00                     3.00
    01/05/2012      0.00                     4.00
    01/06/2012      0.00                     5.00
    01/07/2012      0.00                     6.00
    
    然而,这可能不是性能最好的解决方案 这是最容易实现的,接受两个查询,同时运行两个查询,并合并结果。但是SQL Server支持聚合函数,可以对结果进行分区。您可能有兴趣研究的语义,以便了解如何仅在单个查询中运行报表。我自己也实现过类似的查询,但通常使用
    SUM
    s,而不是
    AVG
    s。我会用OVER子句提供一个解决方案的可能实现,但它可能有点过于复杂,我担心我会搞砸结果的正确平均。事实上,现在我想起来了,像这样的东西可能很好用:

    SELECT FH.ShipDate
         , AVG(CASE WHEN VendorName = 'Atlantic Trucking'  THEN FH.[Dist Freight] ELSE NULL END) AS [Atlantic Freight Charge]
         , AVG(CASE WHEN VendorName != 'Atlantic Trucking' THEN FH.[Dist Freight] ELSE NULL END) AS [Non-Atlantic Freight Charge]
      FROM dbo.vw_FreightHistory as FH
     GROUP BY ShipDate
     ORDER BY ShipDate
    
    但我忘了AVG是否计算空行


    无论如何,我希望我已经回答了您的问题,并帮助您理解了为什么您的查询出现问题。

    您能展示一下表结构、一些数据并解释一下您要做的事情吗?喜欢你的问题。如果我们只知道您希望它做什么,它可能会以一种简单的方式重新编写。与您的错误消息无关,但您似乎缺少一个结束括号。@DanBracuk括号很好,不缺少任何内容[非大西洋运费]返回多个结果。您已经建立了每个日期的平均值,因此,如果您提取今天和明天的平均值,您的独特[非大西洋运费]将返回2个结果。@DavidSöderlund这是一个相当大的表,但我尝试使用的属性是ShipDate、VendorName和Dist运费。基本上,我要做的是显示一个特定供应商名称的平均“Dist运费”成本趋势,然后在另一列中显示所有其他供应商的平均成本。输出应为三列:每个不同的发货日期、供应商A在该日期的平均运费以及所有其他供应商的平均运费。抱歉,我更正了我的脚本。在case语句中实际应该使用NULL而不是0。这似乎工作得很好。我不知道您可以使用SQL中的用例(我是一个非常优秀的程序员)