我想从表中为每个项目类型选择“最佳”行(即具有最大/最小分数的行)。
举一个简单的例子,假设我对不同类型水果的不同颜色有多受欢迎,并确定了一些水果颜色组合的以下分数:
Fruit | Color | Score
==========================
apples | red | 5
apples | yellow | 5
apples | green | 4
apples | blue | 0
bananas | brown | 1
bananas | blue | 0
bananas | yellow | 5
kiwis | orange | 1
kiwis | brown | 5
kiwis | blue | 0
现在我想告诉我的产品设计团队他们应该为每种水果选择什么颜色。如果两种颜色同样受欢迎,我希望按字母顺序排在第一位,只是为了得到确定的结果。
执行此操作的正常方法可能是编写一个程序,在数据库中查询所有水果列表(伪代码),然后运行这样的foreach:
result = query("SELECT DISTINCT fruit FROM fruits;")
foreach fruit in result:
color = query("SELECT color FROM fruits WHERE fruit='$fruit' ORDER BY score DESC, color LIMIT 1")
print "The $fruit should be $color."
如果我想在SQL中执行此操作,我可以计算子查询中的分数,然后选择与分数匹配的行或连接它们(使用MIN和GROUP BY来消除可能的重复项):
SELECT fruit, MIN(color) FROM
fruits
JOIN
(SELECT fruit, max(score) AS score FROM fruits GROUP BY fruit)
USING (fruit, score)
GROUP BY fruit
您可以在this SQL Fiddle。
中找到示例数据和此查询有没有更优雅的方法只在SQL / SQLite中解决这个问题?
在这个简单的例子中,连接本身可能看起来不是太糟糕,因为我可以通过MAX + GROUP BY技巧摆脱重复。如果我需要选择其他列,例如愿意以这种颜色购买水果的人数,我将不得不再次嵌入查询 。这导致像这样的怪物:
SELECT fruit, color, interested FROM
(
SELECT fruit, color, interested FROM
fruits
JOIN
(SELECT fruit, max(score) AS score FROM fruits GROUP BY fruit)
USING (fruit, score)
)
JOIN
(
SELECT fruit, min(color) as color FROM
fruits
JOIN
(SELECT fruit, max(score) AS score FROM fruits GROUP BY fruit)
USING (fruit, score)
GROUP BY fruit
)
USING (fruit, color)
(怪物为Fiddle)
答案 0 :(得分:2)
将两个排序列组合成单个值可以使用简单的MIN。 这需要formatting得分值作为固定长度的字符串:
SELECT fruit,
MIN(printf("%10d", score) || color)
FROM fruits
GROUP BY fruit
在SQLite 3.7.11或更高版本中,保证非聚合列来自与MIN / MAX匹配的相同记录(changelog):
SELECT fruit,
score,
color,
interested,
MIN(printf("%10d", score) || color)
FROM fruits
GROUP BY fruit
答案 1 :(得分:0)
编辑:我现在能想到的最好是遵守字母顺序:
SELECT fruit, min(color) AS color
FROM (
SELECT fruit, color, score, interested
FROM fruits AS f1
GROUP BY fruit, score, color
HAVING score = (
SELECT MAX(score)
FROM fruits AS f2
WHERE f2.fruit = f1.fruit
)
)
GROUP BY fruit
这会回答您的第一个问题,并返回您要求的正确fruit
,color
对。
如果您想选择其他列,您可以使用此查询的结果计算出您感兴趣的行(例如,一旦您知道"苹果应为蓝色" 您可以使用这些值再次查询表格。)
实际上
SELECT fruit, min(color), score, interested FROM (
也有效,但这是不好的做法,某些数据库甚至都不支持。
希望这有帮助。