2010-05-28 27 views
0

編輯:我的歉意,這是一個MSSQL2008問題。選擇符合條件的首選項的方法

我有一個SQL問題,我反對例行公事,通常只是解決W /嵌套查詢。我希望有人能提出更優雅的解決方案。

它經常發生,我需要選擇一個用戶的結果集,條件是它是最近的,或最大的或任何。

例如:他們創建的頁面的完整列表,但我只想要他們應用於頁面的最新名稱。恰巧,數據庫包含每個頁面的許多條目,並且只有最近的條目是所需的。

我一直在使用嵌套選擇,如:

SELECT pg.customName, pg.id 
FROM (
    select id, max(createdAt) as mostRecent 
    from pages 
    where userId = @UserId 
    GROUP BY id 
) as MostRecentPages 
JOIN pages pg 
ON pg.id = MostRecentPages.id 
AND pg.createdAt = MostRecentPages.mostRecent 

是否有更好的語法來執行這個選擇?

回答

-1

我不知道你的表是什麼樣子

Select top 1 pg.createdAt 
      ,pg.customName 
      ,pg.id 
from   table pg 
where   pg.UserId = @UserId 
order by  pg.createdAt Desc 

我需要你的桌

0

是否使用甲骨文多一點信息?試着看看這個使用分析函數的查詢是否適合你。 (您還沒有訪問權現在分貝,所以無法測試自己。)

SELECT DISTINCT pg.id, 
FIRST_VALUE(pg.customName) OVER (PARTITION BY pg.id ORDER BY pg.createdAt DESC) AS customName 
FROM pages pg 
+0

假設pg.id是一個標識列是'選擇不同'需要?或者是因爲分組? – Darknight 2010-05-28 18:25:00

+0

看看原作者的查詢,pg.id似乎不是一個標識列。 – Tommi 2010-05-29 07:03:05

0

假設SQL Server和頁面表所示:

CREATE TABLE Pages (
    Id int IDENTITY(1, 1) PRIMARY KEY 
    , CustomName nvarchar(20) NOT NULL 
    , CreatedAt datetime NOT NULL DEFAULT GETDATE() 
    , UserId int references Users(Id) 
) 

我會做到以下幾點:

select TOP 1 p.Id as PageId 
     , p.CustomName 
    from Pages p 
    where p.UserId = @UserId 
    order by p.Created desc 

甚至:

select TOP 1 p.Id as PageId 
     , p.CustomName 
     , MAX(p.CreatedAt) DateTimeCreated 
    from Pages p 
    where p.UserId = @UserId 
    group by p.Id 
     , p.CustomName 

我希望這有幫助! (如果沒有,請提供更多的細節,以便我們更好地伸出援助之手)的

+0

這些不起作用。第一個將獲得用戶的頂級ID - 而不是每個用戶的每頁。第二個會抱怨,因爲你已經混合了列引用的聚合並且沒有GROUP BY。 – 2010-05-30 20:23:17

+0

謝謝!我忘記了將*組包括到我的查詢中。我編輯過。 – 2010-05-31 10:53:25

1

我不知道更好,但不同的語法,你可以嘗試是

SELECT pg.customName, pg.id 
FROM pages pg 
WHERE userId = @UserId 
AND NOT EXISTS 
     (
     SELECT * FROM pages pg2 
     WHERE pg2.UserId = pg.UserId 
     AND pg2.id = pg.id 
     AND pg2.createdAt > pg.createdAt 
     ) 

另一種方法是一個OUTER JOIN如Bill Karwin在這裏的答案How to get all the fields of a row using the SQL MAX function?

1

對於什麼數據庫(包括版本)?什麼你貼可能是MySQL和SQL Server或Sybase ...

使用:

SELECT pg.customName, 
     pg.id 
    FROM PAGES pg 
    JOIN (SELECT t.userid, 
       MAX(t.createdAt) as mostRecent 
      FROM PAGES t 
     GROUP BY t.userid) x ON x.id = pg.id 
          AND x.mostRecent = pg.createdAt 
          AND x.userid = @UserId 

這是一個便攜式查詢的最佳方法,假設列引用是正確的。但有限制數據集的備選方案--SQL Server使用TOP,MySQL/Postgre/SQLite使用LIMIT,Oracle使用ROWNUM

什麼是最好的取決於你的數據&相應的優化器如何看待它,以及你的需求(便攜與非)。檢查相應數據庫的解釋計劃以查看查詢的效率。

+0

這是MSSQL 2008 - 那麼這個嵌套查詢與我發佈的查詢有什麼不同呢,除了參數化謂詞在嵌套查詢之外進行操作之外呢?這是否會提高性能?我想這取決於表格的索引。 – jkelley 2010-06-01 20:09:34

2

看起來像你想

SELECT id, customname 
FROM (SELECT id, customname, 
      row_number() OVER(PARTITION BY id ORDER BY createdat DESC) as pos 
     FROM pages 
     WHERE pages.userid = @UserId 
    ) x 
WHERE x.row_number = 1 

(我假設你正在使用SQL Server從@UserId參數。ROW_NUMBER()將SQL Server 2005的工作,和TBH上面還應該工作Oracle,Postgresql 8.4 ...)

這將按用戶ID選擇所有頁面,並使用排序來確定哪個是最近的頁面。另一種方法是某事像:

SELECT id, (SELECT TOP 1 customname 
      FROM pages pages_inner 
      WHERE pages_inner.id = pages_outer.id 
      ORDER BY pages_inner.createdat DESC) as customname 
FROM (SELECT DISTINCT id FROM pages WHERE pages.userid = @UserId) pages_inner 

哪種方法更好取決於有多少頁行每個ID已比較每個用戶ID的網頁,我猜。