查询仅在其所有产品处于特定条件时返回值

时间:2014-11-24 18:58:55

标签: mysql

我有一个select,它返回一个表,如下例所示。

list    product location    created
790525  535107  A13.01  2014-08-05 10:47:45
790525  535107  A33.04  2014-08-05 10:47:45
798899  502279  A21.06  2014-06-16 14:27:11
798899  502284  A19.03  2014-06-16 14:00:40
798899  502284  C.06.12 2014-06-16 14:00:40
804005  624390  C.19.00 2014-10-07 16:10:44
804005  624390  A.17.07 2014-10-07 16:47:08
804005  625333  C.01.01 2014-10-05 14:00:01
804738  537045  C.41.06 2014-08-04 18:20:08

此查询已按列表和产品分组,并按创建日期排序。我似乎无法找到一种方法来创建一个返回所有列表编号的查询,其中所有产品的位置都以" A"因为它是最古老的地方。

在上面的示例中,它将返回790525(其唯一产品的最旧位置是A13.01),798899(其产品的最早位置以A开头)并且没有其他内容。因为剩余的列表没有以A开头的最旧位置。

这里有人可以围绕这个吗?我在一个查询中需要这个,但此时任何解决方案都是受欢迎的。

2 个答案:

答案 0 :(得分:0)

正如评论所指出的,您正在寻找每组最大的N项。在这种情况下,您希望获得每个组中最早的项目,您可以这样做:

SELECT *
FROM myTable m
WHERE(
  SELECT COUNT(*)
  FROM myTable mt
  WHERE mt.list = m.list AND mt.created <= m.created) <= 1;

然后,您所要做的就是过滤位置以A开头的行。您可以使用通配符执行此操作:

SELECT *
FROM myTable m
WHERE(
  SELECT COUNT(*)
  FROM myTable mt
  WHERE mt.list = m.list AND mt.created <= m.created) <= 1
AND m.location LIKE 'A%';

以下是获取组内行的SQL Fiddle和更多information

答案 1 :(得分:0)

使用没有OLAP函数的SQL这种查询很难 - 我怀疑使用OLAP函数可能会更容易,但我不够专业,无法确定。 MySQL 5.7似乎不支持允许您命名子查询的WITH子句,这使得它更复杂。

我通过我称之为TDQD - 测试驱动的查询设计来解决这些问题。我分阶段构建查询,每个阶段都可以单独测试。如有必要,可以进行更正。

我正在使用我comment中提出的重新构造的查询:

  

[R]将问题改为:选择列表中的所有数据,其中最旧行中的位置以A开头的产品计数与该列表中的产品计数相同。

这些部分标题中的Q是'查询',而不是'问题'。

Q1 - 生成问题

中显示的表格

问题中显示的表本身就是复杂查询的结果。但我们必须在这里写点东西。因此,我们假设生成该结果的查询是:

SELECT list, product, location, created FROM prodlist

此表达式将(经常)出现在后续查询中。您应该考虑创建生成结果的视图是否有意义,或者是否创建包含结果的临时表,或者是否只是在每次出现时将其全部写出来。

Q2 - 每个列表中的项目数

SELECT list, COUNT(DISTINCT product) AS num_products
  FROM (SELECT list, product, location, created FROM prodlist) AS p
 GROUP BY list

Q3 - 列表中每个产品的最旧条目

SELECT list, product, MIN(created) AS oldest
  FROM (SELECT list, product, location, created FROM prodlist) AS p
 GROUP BY list, product

Q4 - 列表中每个产品的最旧条目的第一个字母位置

这将Q3的结果与Q1中的数据结合起来:

SELECT p.list, p.product, SUBSTR(p.location, 1, 1) AS loc_code
  FROM (SELECT list, product, location, created FROM prodlist) AS p
  JOIN (SELECT list, product, MIN(created) AS oldest
          FROM (SELECT list, product, location, created FROM prodlist) AS p
         GROUP BY list, product) AS o
    ON p.list = o.list AND p.product = o.product AND p.created = o.oldest

Q5 - 每个列表的产品数量,其中最旧的条目位于以A

开头的位置

这总结了Q4的温和修改版本:

SELECT list, COUNT(*) AS num_products
  FROM (SELECT p.list, p.product
          FROM (SELECT list, product, location, created FROM prodlist) AS p
          JOIN (SELECT list, product, MIN(created) AS oldest
                  FROM (SELECT list, product, location, created
                          FROM prodlist) AS p
                 GROUP BY list, product) AS o
            ON p.list = o.list AND p.product = o.product AND
               p.created = o.oldest
         WHERE SUBSTR(p.location, 1, 1) = 'A') AS n
 GROUP BY list

Q6 - 列出Q2和Q5中项目数相同的位置

Q2和Q5为我们提供了每个列表需要比较的两个数字。我们只对数字相同的列表感兴趣,因此我们可以加入两个子查询:

SELECT c1.list
  FROM (SELECT list, COUNT(DISTINCT product) AS num_products
          FROM (SELECT list, product, location, created FROM prodlist) AS p
         GROUP BY list
       ) AS c1
  JOIN (SELECT list, COUNT(*) AS num_products
          FROM (SELECT p.list, p.product
                  FROM (SELECT list, product, location, created
                          FROM prodlist) AS p
                  JOIN (SELECT list, product, MIN(created) AS oldest
                          FROM (SELECT list, product, location, created
                                  FROM prodlist) AS p
                         GROUP BY list, product) AS o
                    ON p.list = o.list AND p.product = o.product AND
                       p.created = o.oldest
                 WHERE SUBSTR(p.location, 1, 1) = 'A') AS n
         GROUP BY list
       ) AS c2
    ON c1.list = c2.list AND c1.num_products = c2.num_products

Q7 - Q6

列表中每个项目的完整信息

这简单地将Q6的结果与原始查询结合以获得正确的数据。当您遇到问题时,不会想到那种查询,但如果您按照这些步骤操作,则一切都有意义。如果您已经测试了每个步骤,那么您就知道在每个步骤中需要调试的内容 - 此步骤中的新材料,而不是之前步骤中的旧材料。

SELECT p.*
  FROM (SELECT list, product, location, created FROM prodlist) AS p
  JOIN (SELECT c1.list
          FROM (SELECT list, COUNT(DISTINCT product) AS num_products
                  FROM (SELECT list, product, location, created
                          FROM prodlist) AS p
                 GROUP BY list
               ) AS c1
          JOIN (SELECT list, COUNT(*) AS num_products
                  FROM (SELECT p.list, p.product
                          FROM (SELECT list, product, location, created
                                  FROM prodlist) AS p
                          JOIN (SELECT list, product, MIN(created) AS oldest
                                  FROM (SELECT list, product, location, created
                                          FROM prodlist) AS p
                                 GROUP BY list, product) AS o
                            ON p.list = o.list AND p.product = o.product AND
                               p.created = o.oldest
                         WHERE SUBSTR(p.location, 1, 1) = 'A') AS n
                 GROUP BY list
               ) AS c2
            ON c1.list = c2.list AND c1.num_products = c2.num_products
       ) AS q
    ON p.list = q.list
 ORDER BY p.list, p.product, p.created

请注意,Q1表达式在Q7中出现4次。

设计和开发查询可能很困难。分阶段构建和测试通常会使过程更容易,就像将程序分解为函数一样,可以更容易地编写程序。


警告: 未经测试的代码