【问题标题】:Using Union All with Multiple Sub Queries to return Total使用 Union All 和多个子查询返回 Total
【发布时间】:2016-06-04 04:29:23
【问题描述】:

我有一个查询可以提取当天的各种每日统计信息。

这是我的查询:

SELECT     e.Location_Name AS Location, c.customers AS Customers, '$' + CONVERT(nvarchar, CAST(c.net_sales AS money), 1) AS Sales, '$' + CONVERT(nvarchar, 
           CAST(e.Ticket_Goal AS Decimal(10, 2))) AS [TKT Goal], '$' + CONVERT(nvarchar, c.Ticket_avg) AS TKT, CAST(d.Labor_Hours / c.customers AS Decimal(10, 2)) 
           AS Labor, CONVERT(nvarchar, CAST(d.Labor_Dollars / c.net_sales * 100 AS Decimal(10, 1))) + '%' AS [%]
FROM         (SELECT Store_Number, SUM(Net_Sales) AS net_sales, SUM(Customers ) AS Customers , CAST(SUM(Net_Sales) / SUM(Customers ) AS decimal(10, 2)) 
                                              AS Ticket_avg
                       FROM  daily_sales_tb AS a
                       WHERE (Operations_Day = DATEADD(d, DATEDIFF(d, 0, GETDATE()), 0))
                       GROUP BY Store_Number) AS c INNER JOIN
                          (SELECT     Store_Number, SUM(Labor_Hours) + SUM(Overtime_Labor_Hours) AS Labor_Hours, SUM(Labor_Dollars) + SUM(Overtime_Labor_Dollars) 
                                                   AS Labor_Dollars
                            FROM          daily_labor_tb AS b
                            WHERE      (Operations_Day = DATEADD(d, DATEDIFF(d, 0, GETDATE()), 0))
                            GROUP BY Store_Number) AS d ON c.Store_Number = d.Store_Number INNER JOIN
                          (SELECT     Store_Number, Ticket_Goal, Location_Name
                            FROM          dds.Location_Table_Info_Tb) AS e ON c.Store_Number = e.Store_Number

这是输出:

Location       Customers      Sales    TKT Goal   TKT   Labor   %
1                 100        $1000      $9.00     $10     1.2  20%
2                 200        $1500      $9.00     $7.50   1.3  15%
3                 300        $2000      $9.00     $6.67   1.4  20%
4                 100        $800       $9.00     $8      1.1  20%

这是我希望输出的样子(添加总行):

 Location            Customers      Sales    TKT Goal   TKT   Labor   %
    1                 100        $1,000      $9.00     $10     1.2  20%
    2                 200        $1,500      $9.00     $7.50   1.3  15%
    3                 300        $2,000      $9.00     $6.67   1.4  20%
    4                 100        $800        $9.00     $8      1.1  20%
   TOTAL:             900        $5,300       -        $5.89    -    - 

我已尝试使用 Union All -

SELECT     e.Location_Name AS Location, c.customers AS Customers, '$' + CONVERT(nvarchar, CAST(c.net_sales AS money), 1) AS Sales, '$' + CONVERT(nvarchar, 
                      CAST(e.Ticket_Goal AS Decimal(10, 2))) AS [TKT Goal], '$' + CONVERT(nvarchar, c.Ticket_avg) AS TKT, CAST(d.Labor_Hours / c.customersAS Decimal(10, 2)) 
                      AS Labor, CONVERT(nvarchar, CAST(d.Labor_Dollars / c.net_sales * 100 AS Decimal(10, 1))) + '%' AS [%]
FROM         (SELECT     Store_Number, SUM(Net_Sales) AS net_sales, SUM(Customers ) AS Customers , CAST(SUM(Net_Sales) / SUM(Customers ) AS decimal(10, 2)) 
                                              AS Ticket_avg
                       FROM          daily_sales_tb AS a
                       WHERE      (Operations_Day = DATEADD(d, DATEDIFF(d, 0, GETDATE()), 0))
                       GROUP BY Store_Number) AS c INNER JOIN
                          (SELECT     Store_Number, SUM(Labor_Hours) + SUM(Overtime_Labor_Hours) AS Labor_Hours, SUM(Labor_Dollars) + SUM(Overtime_Labor_Dollars) 
                                                   AS Labor_Dollars
                            FROM          daily_labor_tb AS b
                            WHERE      (Operations_Day = DATEADD(d, DATEDIFF(d, 0, GETDATE()), 0))
                            GROUP BY Store_Number) AS d ON c.Store_Number = d.Store_Number INNER JOIN
                          (SELECT     Store_Number, Ticket_Goal, Location_Name
                            FROM          dds.Location_Table_Info_Tb) AS e ON c.Store_Number = e.Store_Number

                            UNION ALL
                            select 'TOTAL:', SUM(Customers ), '$' + Convert(nvarchar,Cast(SUM (net_sales) as money),1), '-', Convert(nvarchar,CAST(SUM(Net_Sales) / SUM(Customers ) AS money)), '-', convert(nvarchar,'-')
                            from daily_sales_tb

当我运行这个查询时,我得到一个 SQL 错误:

Msg 8115, Level 16, State 6, Line 1
Arithmetic overflow error converting varchar to data type numeric.

如何解决这个问题以正确输出数据?

我在 vb.net 中运行此查询,填​​充数据集,然后将数据集转换为 HTML 表。转换完成后,我将表格作为电子邮件正文通过电子邮件发送。

【问题讨论】:

  • SQL Server 没有 ROLLUP 或类似的东西,可以用来代替 UNION ALL 吗?
  • 您确实应该在显示层中完成大部分显示内容(无论您的前端是什么)。
  • 我正在使用 vb.net - 但是,我正在将数据集转换为 HTML 表,并通过电子邮件发送出去。在两者之间添加它不是一个很好的选择。
  • 该错误是因为您试图在第一列中混合数据类型。您需要将第一列转换为 varchar 才能正常工作。

标签: sql sql-server vb.net sql-server-2008 dataset


【解决方案1】:

您的第一个选择中有CAST(d.Labor_Hours / c.customers AS DECIMAL(10,2)) AS Labor,您的联合中有'-'。只需将Labor 转换为NVARCHAR,就像您是主选择中的其余值一样

【讨论】:

    【解决方案2】:

    问题是查询试图将文本“TOTAL:”转换为数字。这样做是为了匹配该列中具有“Store_Number”的先前查询。要解决此问题,请尝试将“Store_Number”转换为字符类型:

    改变这个:

    SELECT     Store_Number
    

    到这里:

    SELECT     Convert(nvarchar,Store_Number) as Store_Number,
    

    【讨论】:

    • 您指的是主查询“Location”中的第一个选择,还是您指的是我引用“Store_Number”的子查询我转换了“Location_Name”的初始选择并且我'仍然出现同样的错误。
    • 子查询。当您执行联合(或全部联合)时,所有列都需要具有相同的数据类型。也就是说,所有查询的第一列需要具有相同的数据类型。秒数都需要匹配,三分之二等等。
    【解决方案3】:

    由于您没有提到列的确切数据类型,解决方案只是检查这两个事情,它应该可以解决错误:

    1. UNION ALL 之前的列类型应与 UNION ALL 之后的列类型匹配。这意味着如果列是 Varchar 类型,则在 UNION ALL 语句之前和之后应该存在相同的 Varchar 类型。

    2. 您可能需要检查表的原始列类型、您在查询中使用的转换类型以及“确保该字段实际上可转换为您尝试转换的类型”(例如: 'TOTAL: 如果第一列(位置)是文本字段,则可以在 UNION ALL 中添加,但如果它是整数字段,则会抛出错误)- 需要对所有列进行类似的检查

      李>

    注意:发生错误是因为您尝试将文本字段转换为原始字段中没有兼容的十进制值的十进制

    【讨论】:

    • 原始查询运行完成。一旦添加了 Union All 查询 - 就是我收到错误的时候。
    猜你喜欢
    • 2018-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-27
    • 2014-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多