【问题标题】:Counting quantities using join and nested queries使用联接和嵌套查询计算数量
【发布时间】:2014-09-24 20:24:21
【问题描述】:

我正在尝试从存储在 xcart_order_details 中的有效销售订单中计算库存数量。我还想只计算 x 天内下达的订单中的库存,这些订单的状态为“已处理”“P”或“排队”“Q”,以及库存类型是否与某些位置匹配; C1 库存、C2 库存等。

这在我们旧的 xcart 数据库中曾经相对简单;

SELECT COUNT(`amount`)
FROM `xcart_order_details`
WHERE `productid` IN (
  SELECT `productid`
  FROM `xcart_products` WHERE `orderid` IN
    (SELECT `orderid`
     FROM `xcart_orders`
     WHERE `date` > ".$date_range."
       AND (`status` = 'P'
            OR `status` = 'Q'))
  AND (LOWER(param01) = 'c1 stock'
       OR LOWER(param01) = 'c2 stock'
       OR LOWER(param01) = 'g stock'
       OR LOWER(param01) = 'stock')
  AND `productid` = ".$safe_prodid.")

此查询有效。但是现在我们的库存位置存储在另一个名为 xcart_extra_field_values 的表中,并且必须在 fieldid = 5 的地方检索;

我尝试使用连接从 xcart_extra_field_values 中的 fieldid = 5 获取值字段,并尝试执行我正在执行的上述查询,但它不起作用。

SELECT COUNT(`a.amount`)
FROM xcart_order_details a,
     xcart_extra_field_values b
WHERE a.productid IN (
  SELECT productid
  FROM xcart_products WHERE orderid IN
    (SELECT orderid
     FROM xcart_orders
     WHERE date > 1409529600
       AND (status = 'P'
            OR status = 'Q'))
  AND (LOWER(b.value) = 'c1 stock'
       OR LOWER(b.value) = 'c2 stock'
       OR LOWER(b.value) = 'g stock'
       OR LOWER(b.value) = 'stock')
  AND (a.productid = b.productid)
  AND (a.productid = 4169)
  AND (b.fieldid = 5)

不幸的是,这个查询不起作用,我知道这是一个语法问题,但我得到的错误没有任何帮助。

谁能解释我做错了什么?

【问题讨论】:

  • 你得到什么错误?
  • 我得到:“#1064 - 您的 SQL 语法有错误;请查看与您的 MySQL 服务器版本相对应的手册,以在第 19 行的 '' 附近使用正确的语法”事后诸葛亮是有道理的,但当时并不清楚。
  • 奇怪的是,顺便说一句,您计算有数量的记录。如果这是故意的,并且您没有从表中选择任何其他值,那么如果您在 WHERE 子句 (AND amount IS NOT NULL)) 中排除 NULL 并改为计数记录 (COUNT(*)),它将更具可读性。如果数量永远不会为 NULL,而不是计数记录(再次COUNT(*)),而不是数量的非空出现,无论如何都不能为空。 (当然,如果你想计算总金额,你可以SUM这些金额来得到这个总数。)

标签: mysql sql


【解决方案1】:

您缺少如何连接两个表的条​​件。假设表 xcart_extra_field_values 中有一个 xcart_order_details_id,然后使用它。

毕竟,您甚至不必加入。您想要来自 xcart_order_details 的结果,其中某些详细值记录 EXIST:

SELECT COUNT(`amount`)
FROM `xcart_order_details`
WHERE `productid` IN 
(
  SELECT `productid`
  FROM `xcart_products` 
  WHERE `orderid` IN
  (
    SELECT `orderid`
    FROM `xcart_orders`
    WHERE `date` > ".$date_range."
    AND `status` IN ('P','Q')
  )
AND `productid` = ".$safe_prodid."
AND EXISTS
(
  SELECT *
  FROM xcart_extra_field_values v
  WHERE v.xcart_order_details_id = xcart_order_details.id
  AND fieldid = 5
  AND LOWER(param01) IN ('c1 stock','c2 stock','g stock','stock')
);

顺便说一句:你数一下有多少订单明细记录有金额?

【讨论】:

  • 这可能是正确的,但看起来像是一种完全不同的方式来做我正在做的事情,我现在已经让我的查询工作了。我会看看这个方法,看看它是否更有效。加入我的表的条件在我的查询中 (a.productid = b.productid)
  • 既然您提到了它;-) 我的查询与您的原始查询不完全一样。顺便说一句,你的也没有。当它应该具有所需的日期范围和状态 特定的股票条目时,我的会为您提供所需日期范围内的所有记录和状态 并且 具有特定的股票条目。当产品恰好在 xcart_extra_field_values 中为所需位置提供一些记录时,您的查询会为您提供所需日期范围和状态的记录。我会给你一个额外的评论你的答案。
  • 是的,我已经更正了自己的答案。 xcart_extra_field_values 将始终包含每个产品的条目。我基本上是从活跃客户订单中计算库存 x 天,其中库存位于特定仓库位置。
【解决方案2】:

已解决。

SELECT COUNT(a.amount)
FROM xcart_order_details a,
     xcart_extra_field_values b
WHERE a.productid IN
    (SELECT productid
     FROM xcart_products
     WHERE orderid IN
         (SELECT orderid
          FROM xcart_orders
          WHERE date > 1409529600
            AND (status = 'P'
                 OR status = 'Q'))
       AND (LOWER(b.value) = 'c1 stock'
            OR LOWER(b.value) = 'c2 stock'
            OR LOWER(b.value) = 'g stock'
            OR LOWER(b.value) = 'stock'))
       AND (a.productid = b.productid)
       AND (a.productid = 4169)
       AND (b.fieldid = 5)

首先,当我嵌套两个 IN 查询时,我在查询末尾缺少一个括号,我需要删除 COUNT 中 a.amount 周围的 Grave 重音,这是它不喜欢的。当我并排查看查询时,我才注意到缺少的括号。

编辑:将我的联接移到嵌套的 IN 子句之外,因为嵌套它没有任何意义。

【讨论】:

  • 1.确保您正确加入。 xcart_order_details 和 xcart_extra_field_values 不仅会通过 productid 连接,是吗? 2. 在 IN 子句中进行交叉连接然后丢弃连接的结果记录是很奇怪的。这是可能的,但不是真正可读的。它看起来不是有意的,所以第三个人可能会推测查询中的缺陷。 3. 你应该远离容易出错的逗号分隔连接语法,这种语法在标准 SQL 中被显式连接(INNER JOIN、CROSS JOIN 等)取代了二十多年。
  • extra_field_values 表将始终包含与 productid 匹配的内容,因此不会丢弃任何内容。无论如何,Join 不需要在 IN 子句中,我应该可以通过将主要 IN 子句的末尾移到执行 join 之前将其取出。
  • 用“丢弃”我的意思是:你交叉连接两个表。如果每个都有 1000 行,您将获得一百万条结果记录,但是您会从结果中丢弃记录。您可以使用 IN 子句这样做,但是在该 IN 子句中您使用来自外部(来自相关记录)的值,这是非常罕见的。这是一个技巧,它有效,但你必须小心并知道你实际上在做什么。它不被认为是非常可读或可维护的。
  • 我不太关注。在我的 join 子句中,我选择 a.productid = 4169 的结果,所以我的 join 应该只返回一个结果,不是吗?
  • 抱歉,我错过了您的上次编辑,您将一些 WHERE 子句移到了 IN 子句之外。对于 xcart_extra_field_values,每个 productid 和 fieldid 总是只有一个条目?那么你是对的。您将 xcart_order_details 与其产品一起加入。 (那我只是想知道为什么您将 xcart_extra_field_values 加入 xcart_order_details 而不是 xcart_products。)
猜你喜欢
  • 1970-01-01
  • 2015-06-16
  • 2020-03-19
  • 2011-04-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-23
  • 2017-12-22
相关资源
最近更新 更多