我有一个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开头的最旧位置。
这里有人可以围绕这个吗?我在一个查询中需要这个,但此时任何解决方案都是受欢迎的。
答案 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是'查询',而不是'问题'。
问题中显示的表本身就是复杂查询的结果。但我们必须在这里写点东西。因此,我们假设生成该结果的查询是:
SELECT list, product, location, created FROM prodlist
此表达式将(经常)出现在后续查询中。您应该考虑创建生成结果的视图是否有意义,或者是否创建包含结果的临时表,或者是否只是在每次出现时将其全部写出来。
SELECT list, COUNT(DISTINCT product) AS num_products
FROM (SELECT list, product, location, created FROM prodlist) AS p
GROUP BY list
SELECT list, product, MIN(created) AS oldest
FROM (SELECT list, product, location, created FROM prodlist) AS p
GROUP BY list, product
这将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
这总结了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
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
这简单地将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次。
设计和开发查询可能很困难。分阶段构建和测试通常会使过程更容易,就像将程序分解为函数一样,可以更容易地编写程序。
警告: 未经测试的代码