簡體   English   中英

SQL查詢以獲取與另一列的MAX值對應的列值?

[英]SQL Query to get column values that correspond with MAX value of another column?

好的,這是我的查詢:

SELECT
  video_category,
  video_url,
  video_date,
  video_title,
  short_description,
  MAX(video_id) 
FROM
  videos
GROUP BY
  video_category

當它提取數據時,我得到了 video_id 的正確行,但它為其他類別提取了每個類別的第一行。 因此,當我獲得類別 1 的 video_id 的最大結果時,我獲得了最大 ID,但獲得了表中 url、日期、標題和描述的第一行。

我怎樣才能讓它拉出與最大 ID 結果相對應的其他列?

編輯:固定。

SELECT
    *
FROM
    videos
WHERE
    video_id IN
    (
        SELECT
            DISTINCT
            MAX(video_id)
        FROM
            videos
        GROUP BY
            video_category
    ) 
ORDER BY
    video_category ASC

我會嘗試這樣的事情:

SELECT
   s.video_id
   ,s.video_category
   ,s.video_url
   ,s.video_date
   ,s.video_title
   ,short_description
FROM videos s
   JOIN (SELECT MAX(video_id) AS id FROM videos GROUP BY video_category) max
      ON s.video_id = max.id

這比您自己的解決方案要快得多

我最近發布了一種新技術來處理 MySQL 中的此類問題。

標量減少

Scalar-Aggregate Reduction 是迄今為止實現這一目標的最高性能方法和最簡單的方法(用數據庫引擎術語來說),因為它不需要連接、子查詢和 CTE。

對於您的查詢,它看起來像這樣:

SELECT
  video_category,
  MAX(video_id) AS video_id,
  SUBSTRING(MAX(CONCAT(LPAD(video_id, 11, '0'), video_url)), 12) AS video_url,
  SUBSTRING(MAX(CONCAT(LPAD(video_id, 11, '0'), video_date)), 12) AS video_date,
  SUBSTRING(MAX(CONCAT(LPAD(video_id, 11, '0'), video_title)), 12) AS video_title,
  SUBSTRING(MAX(CONCAT(LPAD(video_id, 11, '0'), short_description)), 12) AS short_description
FROM
  videos
GROUP BY
  video_category

標量函數和聚合函數的組合執行以下操作:

  1. LPAD 是聚合內相關標識符以允許正確的字符串比較(例如“0009”和“0025”將被正確排序)。 假設 INT 主鍵,我在這里 LPADDING 到 11 個字符。 如果您使用 BIGINT,您將需要增加它以支持您的表的序數。 如果您在 DATETIME 字段(固定長度)上進行比較,則不需要填充。
  2. 使用輸出列連接填充標識符(因此您會得到“00000000009myvalue”與“0000000025othervalue”)
  3. MAX 聚合集,將產生“00000000025othervalue”作為獲勝者。
  4. SUBSTRING 結果,這將截斷比較的標識符部分,只留下值。

如果您想檢索非 CHAR 類型的值,您可能需要對輸出執行額外的 CAST,例如,如果您希望video_date為 DATETIME:

CAST(SUBSTRING(MAX(CONCAT(LPAD(video_id, 11, '0'), video_date)), 12) AS DATETIME)

與自聯接方法相比,此方法的另一個好處是您可以組合其他聚合數據(不僅僅是最新值),甚至可以組合同一查詢中的第一個和最后一個項目,例如

SELECT
    -- Overall totals
    video_category,
    COUNT(1) AS videos_in_category,
    DATEDIFF(MAX(video_date), MIN(video_date)) AS timespan,
    
    -- Last video details
    MAX(video_id) AS last_video_id,
    SUBSTRING(MAX(CONCAT(LPAD(video_id, 11, '0'), video_url)), 12) AS last_video_url,
    ...
    
    -- First video details
    MIN(video_id) AS first_video_id,
    SUBSTRING(MIN(CONCAT(LPAD(video_id, 11, '0'), video_url)), 12) AS first_video_url,
    ...
    
    -- And so on

有關解釋此方法與其他舊方法的優點的更多詳細信息,我的完整博客文章在這里: https : //www.stevenmoseley.com/blog/tech/high-performance-sql-correlated-scalar-aggregate-reduction-queries

這是一個更通用的解決方案(處理重復項)

CREATE TABLE test(
  i INTEGER,
  c INTEGER,
  v INTEGER
);


insert into test(i, c, v)
values
(3, 1, 1),
(3, 2, 2),
(3, 3, 3),
(4, 2, 4),
(4, 3, 5),
(4, 4, 6),
(5, 3, 7),
(5, 4, 8),
(5, 5, 9),
(6, 4, 10),
(6, 5, 11),
(6, 6, 12);



SELECT t.c, t.v
FROM test t
JOIN (SELECT test.c, max(i) as mi FROM test GROUP BY c) j ON
  t.i = j.mi AND
  t.c  = j.c
ORDER BY c;

從視頻 t1 中選擇 video_category,video_url,video_date,video_title,short_description,video_id 其中 video_id 在 (SELECT max(video_id) FROM 視頻 t2 WHERE t1.video_category=t2.video_category );

請提供您的輸入和輸出記錄,以便正確理解和測試。

一個稍微“質朴”的解決方案,但應該做同樣的工作:

SELECT
  video_category,
  video_url,
  video_date,
  video_title,
  short_description,
  video_id
FROM
  videos
ORDER BY video_id DESC
LIMIT 1;

換句話說,只需生成一個包含您想要的所有列的表,對其進行排序,使最大值位於頂部,然后將其切掉,以便只返回一行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM