[英]max in one column and min in another column
例如,如果列A和列B具有值:
+---+---+
| A | B |
+---+---+
| 2 | 1 |
| 5 | 1 |
| 6 | 1 |
| 1 | 2 |
| 5 | 2 |
| 0 | 2 |
| 2 | 3 |
| 7 | 3 |
| 4 | 3 |
| 5 | 4 |
+---+---+
我想從B的每個組中獲得最大的A值。但是,我不想包含B中的數字較高但A值小於上一個值的結果。 我知道這在語言上沒有意義,但這是我希望最終結果看起來像的樣子:
+---+---+
| A | B |
+---+---+
| 6 | 1 |
| 7 | 3 |
+---+---+
到目前為止,我有類似“從表1中按b選擇max(a),b”之類的東西,但這並沒有忽略B較高但max A較小的那些。 我知道我可以在PHP中仔細閱讀該查詢的結果,並刪除A值小於先前A值的那些查詢,但是如果可能的話,我希望將其全部放入mysql查詢中。
該技術將表與自身的聚合版本連接起來,但是該連接偏移了一個 ,因此每一行都連接到前一個B的MAX(A)值的知識上。 然后,它匹配當前A大於其中任何一個的行,並且如果找不到任何行,則不包括該行。 然后,我們匯總最終選擇以得到您想要的結果。
SELECT
MAX(source_row.A) as A,
source_row.B
FROM ab as source_row
LEFT JOIN (SELECT MAX(A) as A, B FROM ab GROUP BY B) AS one_back
ON one_back.B = source_row.B-1
WHERE (one_back.A IS NULL)
OR one_back.A < source_row.A
GROUP BY B
我已經測試過了:-)
我想分享一些我如何提出這類解決方案的見解; 因為我認為對於人們來說,開始“思考集合”很重要……這是我閱讀過的有關JOINS的最佳建議,您需要預想查詢所使用的中間“集合”。 為了說明這一點,這里是中間“集合”的表示形式,它是此查詢的關鍵部分; 它是表,因為它以“一對一”的形式“聯接”到其自身的聚合版本中。
+------+------+------------+------------+
| A | B | one_back.B | one_back.A |
+------+------+------------+------------+
| 2 | 1 | NULL | NULL |
| 5 | 1 | NULL | NULL |
| 6 | 1 | NULL | NULL |
| 1 | 2 | 1 | 6 |
| 5 | 2 | 1 | 6 |
| 0 | 2 | 1 | 6 |
| 2 | 3 | 2 | 5 |
| 7 | 3 | 2 | 5 |
| 4 | 3 | 2 | 5 |
| 5 | 4 | 3 | 7 |
+------+------+------------+------------+
然后,該集合實際上是在內存中創建的(完全連接的版本永遠不會完全存在於內存中,因為MySQL知道知道不會“削減”后就可以立即消除行:
+------+------+------------+------------+
| A | B | one_back.B | one_back.A |
+------+------+------------+------------+
| 2 | 1 | NULL | NULL |
| 5 | 1 | NULL | NULL |
| 6 | 1 | NULL | NULL |
| 7 | 3 | 2 | 5 |
+------+------+------------+------------+
然后,當然,它會將結果從那里匯總為最終形式,僅從原始行中選擇A和B。
一個更簡單的解決方案是使用變量存儲上一行的a
值,並在每次迭代時進行比較。 這也說明了b
列中可能有空格的情況,其中數字並非完全按完美的順序排列:
SELECT @val:=a.a AS a, a.b
FROM
(
SELECT MAX(a) AS a, b
FROM tbl
GROUP BY b
) a
WHERE a.a > IFNULL(@val,-1)
Select Z.a, Z.b from
(select a, b, rank() over (order by b) as ranker from (select max(a) a, b from table1 group by b) Y) Z left join
(select a, b, rank() over (order by b) as ranker from (select max(a) a, b from table1 group by b) Y1) Z1
on Z.ranker = Z1.ranker + 1
where Z.a > isnull(Z1.a, -100000)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.