是否可以在没有临时表的情况下执行此查询?

时间:2011-07-01 20:21:36

标签: sql-server

如果我有这样的数据表

tableid    author     book                 pubdate
1          1          The Hobbit           1923
2          1          Fellowship           1925
3          2          Foundation Trilogy   1947
4          2          I Robot              1942
5          3          Frankenstein         1889
6          3          Frankenstein 2       1894

是否有一个查询可以在不使用临时表,表变量或cte的情况下获得以下内容?

tableid    author     book                 pubdate
1          1          The Hobbit           1923
4          2          I Robot              1942
5          3          Frankenstein         1889

因此,我希望按人分组(排名),并以最小(排名)值结束本书。

好的,我最初提供的数据存在缺陷。而不是排名列,我将有一个日期列。我需要作者最早出版的那本书。

6 个答案:

答案 0 :(得分:3)

错过了CTE无效(但不确定原因)。作为子查询怎么样?

SELECT tableid, author, book, pubdate
FROM
(
    SELECT 
        tableid, author, book, pubdate, 
        rn = ROW_NUMBER() OVER 
        (
            PARTITION BY author
            ORDER BY pubdate
        )
    FROM dbo.src -- replace this with the real table name
) AS x
WHERE rn = 1
ORDER BY tableid;

原件:

;WITH x AS
(
    SELECT 
        tableid, author, book, pubdate, 
        rn = ROW_NUMBER() OVER 
        (
            PARTITION BY author
            ORDER BY pubdate
        )
    FROM dbo.src -- replace this with the real table name
)
SELECT tableid, author, book, pubdate
    FROM x
    WHERE rn = 1
    ORDER BY tableid;

如果要在最早的书籍中存在平局时返回多行,请使用RANK()代替ROW_NUMBER()。如果是平局并且您只想返回一行,则需要在OVER()中向ORDER BY添加额外的tie breaker列。

答案 1 :(得分:1)

select * from table where ranking = 1

修改 您是否正在寻找此查询以在给定表和人员没有rank = 1值的情况下工作?在这种情况下,试试这个:

select *, RANK() OVER (Partition By talbeid, personid order by rank asc) as sqlrank 
from table 
where sqlrank = 1

编辑我的编辑: 这适用于最早的发布日期:

select *, RANK() OVER (Partition By author order by pubdate asc) as sqlrank 
from table 
where sqlrank = 1

答案 2 :(得分:1)

您的样本数据可能过于简单。你谈的是'min(排名)',但是对于你的所有例子,每个personid的最低排名是1.所以你到目前为止收到的答案是短路问题,简单选择排名= 1。你没有在你的“要求”中陈述它,但听起来像任何特定personid的最低等级值可能不一定是1,对吗?此外,您没有提及一个人是否可以对具有相同最低等级的两本或更多书进行排名,因此由于缺少该要求,答案将不完整。

如果我的心灵能力准确,那么你可能想尝试这样的事情(显然未经测试):

SELECT tableid, personid, book, ranking
FROM UnknownTable UNKTBL INNER JOIN 
     (SELECT personid, min(ranking) as ranking 
      FROM UnknownTable GROUP BY personid) MINRANK
     ON UNKTBL.personid = MINRANK.personid AND UNKTBL.ranking = MINRANK.ranking

这将返回每个人的所有行,其中排名值是该人的最小值。因此,如果第6个人的最低排名是2,并且该人排名有两本书,则会返回两个书行。

如果这些不是,实际上是您的要求,那么请使用更多详细信息/示例数据编辑您的问题。谢谢!

修改

根据您对需求/示例数据的更改,如果您正确更改列名,则上述SQL仍然有效。你还没有提到一个作者是否可以在同一年有两本书(即像Stephen King这样多产的作者),所以如果同一作者在同一年出版了两本书,我在这里的SQL会给出多行,那一年是该作者最早出版的一年。

答案 3 :(得分:1)

SELECT tableid,author,book,pubdate FROM my_table as my_table1 WHERE pubdate = 
(SELECT MIN(pubdate) FROM my_table as my_table2 WHERE my_table1.author = my_table2.author);

答案 4 :(得分:1)

WITH min_table as
(
SELECT author, min(pubdate) as min_pubdate
FROM table
GROUP BY author
)
SELECT t.tableid, t.author, t.book, t.pubdate
FROM table t INNER JOIN min_table mt on t.author = mt.author and t.pub_date = mt.min_pubdate

答案 5 :(得分:0)

SELECT * FROM my_table WHERE ranking = 1

ZING!

说真的,虽然我不关注你的问题 - 你能提供更复杂或更复杂的例子吗?我想我错过了一些明显的东西。