查找最小值并包含正确的列值

Posted

技术标签:

【中文标题】查找最小值并包含正确的列值【英文标题】:Find minimum value AND include correct column-values 【发布时间】:2016-08-29 20:48:55 【问题描述】:

我正在尝试获取每次旅行的最低价格,并知道哪些旅行详细信息对应于每次旅行的最低价格。

为此,我尝试了所有类型的子查询、连接等变体,但由于没有 1 个主键,我无法弄清楚。

我想要达到的目的是以最低的价格获得旅行,然后以最低的价格记录旅行的详细信息。

  SELECT travel_id, persons, days, MIN(`price`) AS `price` 
  FROM travel_details
  WHERE 1 
  GROUP BY `travel_id`
  HAVING MIN(price);

我的表格列的简单版本,列是: travel_idpersonsdaysprice

这些列共同构成主键。

可以为不同的人员、日期和价格预订旅行。对于travel_idpersonsdays 的相同组合,也可能存在多个价格选项。

例如,

100, 2,   4, **250**

100, 2,   4, **450**

100, 2, **5**, 450

101, 2,   4,   190

101, 2,   5,   185

成为travel_id 100 2 人 4 人。

我想要实现的是回报: 100、250,然后用正确的对应值:

100、2、4、250

101、2、5、185

现在我的结果只是混合了所有其他数据。当我将这些列包含在 group by 中时,它不仅会在 travel_id 上分组,而且还会在 persons 上分组。然后它将返回 travel_idpersons 的所有组合。

知道如何解决这个问题吗?

【问题讨论】:

在我看来,您接受了错误的答案。如果其他答案对您不起作用,则表明您的设计存在缺陷,而不是该解决方案存在缺陷。 可能是这样,但是如果有这样的评论,请定义设计中的缺陷是什么。具有 4 个列的普通表,所有这些列都需要唯一定义为主键列。或者一个包含 5 个列的普通表,其中 1 个 UID 列作为主键列,4 个包含值的普通列。这样一个基本的表格设置是如何设计缺陷的。问题是如何以最低的价格获得每次旅行 1 完整且正确的记录。当每次旅行有多个选项以相同 - 最低 - 价格但有例如 3 人而不是 4 人时,如何获得每次旅行的这 1 条记录。 对于“记录”,在您发表评论之前,我补充了Sagi的答案。有了最后一个“分组依据”,问题就解决了。所以也许你没有看到,请查看下面的答案。 我非常了解黑客攻击,谢谢。问题是它可能会返回不确定的结果。 【参考方案1】:
    Select a.travel_id, a.persons, a.days, a.price from  travel_details a 
JOIN (Select travel_id,MIN(Price) as p from travel_details group by travel_id) b 
on b.travel_id=a.travel_id and b.p=a.price

上述查询使用自连接。派生表 b 将包含 travel_id 以及最低价格。

【讨论】:

您好“undefined_variable”,感谢您的回复。这种解决方案我也有一个子查询。然而会发生什么,它会导致每组有多个结果。例如:travel_id = 102,在记录#1 中的人 = 3 和在记录#2 中的人 = 4,两者的价格都是例如 200 欧元。上面的查询将返回此 travel_id = 102 的两条记录。无法将“persons”添加到连接查询的选择字符串中,因此也无法添加到主选择查询“b.price = a .price AND b.persons=a.persons"。【参考方案2】:
SELECT travel_id, persons, days, price
FROM (
SELECT
ROW_NUMBER() OVER(PARTITION BY travel_id, persons, days ORDER BY price) AS RowNum, 
travel_id, persons, days, price 
FROM travel_details
) X
WHERE X.RowNum = 1

你好@PeterH,这对你有用吗?

【讨论】:

【参考方案3】:

您可以使用IN() 来执行此操作:

SELECT * FROM travel_details t
WHERE (t.travel_id,t.price) IN(SELECT s.travel_id,min(s.price)
                               FROM travel_details s
                               GROUP BY s.travel_id)
GROUP BY t.travel_id; // this last group-by is to filter doubles when there are multiple records per travel with the lowest price.

【讨论】:

您好 sagi,感谢您的回复。该查询在我的示例数据库上运行超过 3 分钟,只有 20K 条记录,所以我取消了它。它需要在 1 秒内运行。通过多个单一查询,我可以做到这一点。但是我不敢相信 mysql 中没有选项可以在表中选择每组价格最低的记录。还有其他想法吗? 是的,在表的travel_id,price上添加索引。 20k 条记录需要一秒钟@peterh 我同意你的观点,但所有列都是主键,所以它们已经被 mysql 数据库完全索引。其次,这将解决以下响应中指出的“未定义变量”的事实吗?如果有多个最低价格的选项,例如,3 人 200 欧元和 4 人 200 欧元的选项,则认为此查询还将返回每次旅行的多条记录。如何解决它,以便每次旅行只选择一条记录。还是根本不可能.. 到底为什么要设计一个所有列都是主键的表?尝试将索引添加为(travel_id,price) - 一个索引,而不是两个。 @PeterH 多个PK's 很好,不是所有列,但是PK 的价格听起来不太对。许多索引可能会损害性能,这取决于您在表上执行的查询。试试我的想法,在两列上添加一个索引,不管 PK's 并告诉我它是否有帮助,我认为它应该。 @PeterH

以上是关于查找最小值并包含正确的列值的主要内容,如果未能解决你的问题,请参考以下文章

按组和列之间查找最小值

如何将数据库中的列值获取到jLabel

选择最小日期值并计算日期值?

如何找到所有数据框的最大值,最小值[不是列值,也不是行] [重复]

查找具有唯一列的数组中每一行的最小值

显示除零之外的最小值以及每年的相邻列值+ Python 3+,数据框