1

我正在运行一个复杂且昂贵的查询来查找按另一个属性分组的函数的 MIN() 值。但我不仅需要值,我还需要产生它的条目 + 值。

我当前的伪查询是这样的:

SELECT MIN(COSTLY_FUNCTION(a.att1,a.att2,$v1,$v2)) FROM (prefiltering) as a GROUP BY a.group_att;

但我想要a.*MIN(COSTLY_FUNCTION(a.att1,a.att2,$v1,$v2))作为我的结果。

我能想到的唯一方法是使用这个丑陋的野兽:

SELECT a1.*, COSTLY_FUNCTION(a1.att1,a1.att2,$v1,$v2)
FROM (prefiltering) as a1 
WHERE COSTLY_FUNCTION(a1.att1,a1.att2,$v1,$v2) = 
  (SELECT MIN(COSTLY_FUNCTION(a.att1,a.att2,$v1,$v2)) FROM (prefiltering) as a GROUP BY a.group_att) 

但是现在我正在执行 prefiltering_query 2 次,并且必须运行两次代价高昂的函数。这太荒谬了,我希望我在这里做错了什么。

可能的解决方案?:

刚才我意识到我可以创建一个临时表,其中包含:

(SELECT a1.*, COSTLY_FUNCTION(a1.att1,a1.att2,$v1,$v2) as complex FROM (prefiltering) as a1)

然后将 MIN() 作为子查询运行并以大大降低的成本进行比较。这是要走的路吗?

4

2 回答 2

1

您的临时表解决方案的一个问题是我看不到任何方法可以避免在同一个查询中使用它两次

但是,如果您愿意使用实际的永久表(可能带有ENGINE = MEMORY),它应该可以工作。您还可以将子查询移动到FROM子句中,它可能更有效:

CREATE TABLE temptable ENGINE = MEMORY
  SELECT a1.*,
    COSTLY_FUNCTION(a1.att1,a1.att2,$v1,$v2) AS complex
  FROM prefiltering AS a1;

CREATE INDEX group_att_complex USING BTREE
  ON temptable (group_att, complex);

SELECT a2.*
FROM temptable AS a2
  NATURAL JOIN (
    SELECT group_att, MIN(complex) AS complex
    FROM temptable GROUP BY group_att
  ) AS a3;

DROP TABLE temptable;

(你也可以在没有索引的情况下尝试它,但我怀疑它会更快。)

编辑:当然,如果一个临时表不行,你总是可以使用两个:

CREATE TEMPORARY TABLE temp1
  SELECT *, COSTLY_FUNCTION(att1,att2,$v1,$v2) AS complex
  FROM prefiltering;

CREATE INDEX group_att_complex ON temp1 (group_att, complex);

CREATE TEMPORARY TABLE temp2
  SELECT group_att, MIN(complex) AS complex
  FROM temp1 GROUP BY group_att;

SELECT temp1.* FROM temp1 NATURAL JOIN temp2;

(同样,您可能想尝试使用或不使用索引;当我运行EXPLAIN它时,MySQL 似乎根本不想将索引用于最终查询,尽管这可能只是因为我的测试数据集是这么小。无论如何,如果你想玩它,这里有一个 SQLize 的链接CONCAT();我曾经代替你昂贵的功能。)

于 2011-10-15T19:57:50.013 回答
0

除了 MIN 值之外,您还可以使用 HAVING 子句来获取列。例如:

SELECT a.*, COSTLY_FUNCTION(a.att1,a.att2,$v1,$v2) FROM (prefiltering) as a GROUP BY a.group_att HAVING MIN(COSTLY_FUNCTION(a.att1,a.att2,$v1,$v2)) = COSTLY_FUNCTION(a.att1,a.att2,$v1,$v2);
于 2011-10-15T19:19:02.450 回答