【问题标题】:Stuck with this SQL error : "Must declare the scalar variable @XYZ"遇到此 SQL 错误:“必须声明标量变量 @XYZ”
【发布时间】:2015-02-06 00:07:17
【问题描述】:

我正在处理此查询一段时间,但无法找出问题所在。我要做的就是从表中获取信息(最大订单,谁下订单),将其存储并在控制台上将结果作为消息打印出来。感谢您的所有帮助。

这是我的查询:

USE DB;

DECLARE @BigCustomer table(CustomerName varchar(50), Itemtotal smallmoney);

    INSERT @BigCustomer 
        SELECT (FirstName + ' ' + LastName), 
               MAX((ItemPrice - DiscountAmount) * Quantity)
    FROM Orders as o join customers as c 
            on o.CustomerID = c.CustomerID 
         join OrderItems as oi 
              on o.OrderID = oi.OrderID
    WHERE o.CustomerID = 3
    GROUP BY (FirstName + ' ' + LastName), 
             ((ItemPrice - DiscountAmount) * Quantity)

DECLARE @CN nvarchar(50);
SET @CN = (SELECT CustomerName FROM @BigCustomer)
DECLARE @IT smallmoney;
SET @IT = (SELECT ItemTotal FROM @BigCustomer)
DECLARE @PrintMessage nvarchar(50);
SET @PrintMessage = N'The largest order of ' + 
    CONVERT(nvarchar(50), @IT) + N'was made by ' + @CN;

GO
PRINT @PrintMessage

【问题讨论】:

  • 尝试在您的SET @CN = (SELECT CustomerName FROM @BigCustomer) 中使用LIMIT 以及其他SET 命令。
  • 你能提供样本数据和想要的结果吗?如所写,您的group by 声明没有多大意义。您可能不需要任何这些变量...
  • @IT 可能为 NULL。你从来没有设置它。虽然你确实设置了@CN 两次。 SET @CN = (SELECT ItemTotal FROM @BigCustomer) --> SET @IT = (SELECT ItemTotal FROM @BigCustomer) ? CONVERT(nvarchar(50), @IT) 可以使用空值吗?
  • 这...在我看来不像 mysql
  • 这被标记为 MySQL,但语法看起来很像 SQL Server。

标签: sql sql-server sql-server-2012


【解决方案1】:

从您作为答案发布的查询来看,您似乎很困惑。尝试一次做一件事来构建生成的脚本。首先,不要在开头使用变量,而是使用普通查询返回数据。

作为基本查询,请使用仅获得最大订单及其 ID 的查询。为此,只取OrderItems 表就足够了,将数据按OrderID 分组并将结果限制为最高订单总数:

SELECT TOP (1)
  OrderID,
  OrderTotal = SUM((ItemPrice - DiscountAmount) * Quantity)
FROM
  dbo.OrderItems
GROUP BY
  OrderID
ORDER BY
  OrderTotal DESC
;

为了查出上述查询返回的下单客户的ID,可以在Orders添加一个join。您还需要修改 GROUP BY 子句以将 CustomerID 包含在其中:

SELECT TOP (1)
  o.CustomerID,
  oi.OrderID,
  OrderTotal = SUM((oi.ItemPrice - oi.DiscountAmount) * oi.Quantity)
FROM
  dbo.OrderItems AS oi
  INNER JOIN dbo.Orders AS o ON oi.OrderID = o.OrderID
GROUP BY
  oi.OrderID,
  o.CustomerID
ORDER BY
  OrderTotal DESC
;

此时您可以将CustomerID 临时存储到一个变量中,并在第二个查询中使用它从Customers 中读取客户姓名。这并不是必需的,因为您可以在单个查询中返回所有数据:

SELECT TOP (1)
  CustomerName = c.FirstName + ' ' + c.LastName,
  OrderTotal   = SUM((oi.ItemPrice - oi.DiscountAmount) * oi.Quantity)
FROM
  dbo.OrderItems AS oi
  INNER JOIN dbo.Orders AS o ON oi.OrderID = o.OrderID
  INNER JOIN dbo.Customers AS c ON o.CustomerID = c.CustomerID
GROUP BY
  oi.OrderID,
  o.CustomerID,
  c.FirstName,
  c.LastName
ORDER BY
  OrderTotal DESC
;

如您所见,查询中添加了另一个联接,并且再次修改了 GROUP BY 子句,以包括 FirstNameLastName 列。

现在是时候为查询引入变量赋值了,这样您就可以实际存储并打印它们,而不是将结果作为一行返回。

SELECT TOP (1)
  @Customer     = c.FirstName + ' ' + c.LastName,
  @LargestOrder = SUM((oi.ItemPrice - oi.DiscountAmount) * oi.Quantity)
FROM
  dbo.OrderItems AS oi
  INNER JOIN dbo.Orders AS o ON oi.OrderID = o.OrderID
  INNER JOIN dbo.Customers AS c ON o.CustomerID = c.CustomerID
GROUP BY
  oi.OrderID,
  o.CustomerID,
  c.FirstName,
  c.LastName
ORDER BY
  OrderTotal DESC
;

请注意,查询不使用 WHERE 过滤器。您不可能事先知道客户的 ID。正是TOP (1) + ORDER BY 技术可以让您找到它。

【讨论】:

    【解决方案2】:

    雅皮!我想通了。我DECLAREd 两个变量并分别分配参数而不是使用一个变量。

    如果我运行查询,我会收到以下消息:

    $342.30 的最大订单是 Dave Hunter 的。

    这里是查询:

    我想我终于想通了。

    DECLARE @LOrder table(OrdTot money, OrdID int);

    插入@LOrder

    SELECT SUM((OI.ItemPrice - OI.DiscountAmount)*OI.Quantity), OI.OrderID 来自 OrderItems 作为 OI 按订单 ID 分组

    声明@CName varchar(100); 声明@OAmount 钱;

    SET @CName = (SELECT TOP 1 C.FirstName + ' ' + C.LastName FROM 客户 C​​ 加入订单 O on C.CustomerID = O.CustomerID JOIN @LOrder lo on lo.OrdID = O.OrderID ORDER BY lo.OrdTot DESC);

    SET @OAmount = (SELECT TOP 1 奥德托 来自@LOrder 按 OrdTot DESC 订购);

    PRINT '$ 的最大订单' + convert(varchar(50),@OAmount) + ' 是由' + @CName 完成的

    【讨论】:

    • 当 CustomerID 被硬编码并且似乎与拉动最大订单量的查询没有任何联系时,这到底是如何可重用的?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多