it-swarm.com.de

Wählen Sie die 10 besten Datensätze für jede Kategorie aus

Ich möchte die 10 besten Datensätze aus jedem Abschnitt in einer Abfrage zurückgeben. Kann mir jemand helfen, wie es geht? Abschnitt ist eine der Spalten in der Tabelle.

Die Datenbank ist SQL Server 2005. Ich möchte die Top 10 nach dem eingegebenen Datum zurückgeben. Die Abschnitte sind geschäftlich, lokal und funktional. Für ein bestimmtes Datum möchte ich nur die obersten (10) Geschäftszeilen (letzter Eintrag), die obersten (10) lokalen Zeilen und die obersten (10) Funktionen.

188
jbcedge

Wenn Sie SQL 2005 verwenden, können Sie so etwas tun ...

SELECT rs.Field1,rs.Field2 
    FROM (
        SELECT Field1,Field2, Rank() 
          over (Partition BY Section
                ORDER BY RankCriteria DESC ) AS Rank
        FROM table
        ) rs WHERE Rank <= 10

Wenn Ihre RankCriteria gleich ist, geben Sie möglicherweise mehr als 10 Zeilen zurück, und die Lösung von Matt ist möglicherweise besser für Sie.

197
Darrel Miller

In T-SQL würde ich Folgendes tun:

WITH TOPTEN AS (
    SELECT *, ROW_NUMBER() 
    over (
        PARTITION BY [group_by_field] 
        order by [prioritise_field]
    ) AS RowNo 
    FROM [table_name]
)
SELECT * FROM TOPTEN WHERE RowNo <= 10
80
Phil Rabbitt

Dies funktioniert unter SQL Server 2005 (entsprechend Ihrer Erläuterung bearbeitet):

select *
from Things t
where t.ThingID in (
    select top 10 ThingID
    from Things tt
    where tt.Section = t.Section and tt.ThingDate = @Date
    order by tt.DateEntered desc
    )
    and t.ThingDate = @Date
order by Section, DateEntered desc
35
Matt Hamilton
SELECT r.*
FROM
(
    SELECT
        r.*,
        ROW_NUMBER() OVER(PARTITION BY r.[SectionID] ORDER BY r.[DateEntered] DESC) rn
    FROM [Records] r
) r
WHERE r.rn <= 10
ORDER BY r.[DateEntered] DESC
27
lorond

Ich mache es so:

SELECT a.* FROM articles AS a
  LEFT JOIN articles AS a2 
    ON a.section = a2.section AND a.article_date <= a2.article_date
GROUP BY a.article_id
HAVING COUNT(*) <= 10;

pdate: Dieses Beispiel für GROUP BY funktioniert nur in MySQL und SQLite, da diese Datenbanken in Bezug auf GROUP BY toleranter sind als Standard-SQL. Die meisten SQL-Implementierungen setzen voraus, dass sich alle Spalten in der Auswahlliste, die nicht Teil eines Aggregatausdrucks sind, auch in GROUP BY befinden.

18
Bill Karwin

Wenn Sie die Abschnitte kennen, können Sie Folgendes tun:

select top 10 * from table where section=1
union
select top 10 * from table where section=2
union
select top 10 * from table where section=3
9
Blorgbeard

Wenn wir SQL Server> = 2005 verwenden, können wir die Aufgabe nur mit einem select lösen:

declare @t table (
    Id      int ,
    Section int,
    Moment  date
);

insert into @t values
(   1   ,   1   , '2014-01-01'),
(   2   ,   1   , '2014-01-02'),
(   3   ,   1   , '2014-01-03'),
(   4   ,   1   , '2014-01-04'),
(   5   ,   1   , '2014-01-05'),

(   6   ,   2   , '2014-02-06'),
(   7   ,   2   , '2014-02-07'),
(   8   ,   2   , '2014-02-08'),
(   9   ,   2   , '2014-02-09'),
(   10  ,   2   , '2014-02-10'),

(   11  ,   3   , '2014-03-11'),
(   12  ,   3   , '2014-03-12'),
(   13  ,   3   , '2014-03-13'),
(   14  ,   3   , '2014-03-14'),
(   15  ,   3   , '2014-03-15');


-- TWO earliest records in each Section

select top 1 with ties
    Id, Section, Moment 
from
    @t
order by 
    case when row_number() over(partition by Section order by Moment) <= 2 then 0 else 1 end;


-- THREE earliest records in each Section

select top 1 with ties
    Id, Section, Moment 
from
    @t
order by 
    case when row_number() over(partition by Section order by Moment) <= 3 then 0 else 1 end;


-- three LATEST records in each Section

select top 1 with ties
    Id, Section, Moment 
from
    @t
order by 
    case when row_number() over(partition by Section order by Moment desc) <= 3 then 0 else 1 end;
9
Vadim Loboda

Ich weiß, dass dieser Thread ein bisschen alt ist, aber ich bin gerade auf ein ähnliches Problem gestoßen (wähle den neuesten Artikel aus jeder Kategorie aus) und dies ist die Lösung, die ich mir ausgedacht habe:

WITH [TopCategoryArticles] AS (
    SELECT 
        [ArticleID],
        ROW_NUMBER() OVER (
            PARTITION BY [ArticleCategoryID]
            ORDER BY [ArticleDate] DESC
        ) AS [Order]
    FROM [dbo].[Articles]
)
SELECT [Articles].* 
FROM 
    [TopCategoryArticles] LEFT JOIN 
    [dbo].[Articles] ON
        [TopCategoryArticles].[ArticleID] = [Articles].[ArticleID]
WHERE [TopCategoryArticles].[Order] = 1

Dies ist Darrels Lösung sehr ähnlich, überwindet jedoch das RANK-Problem, das möglicherweise mehr Zeilen als beabsichtigt zurückgibt.

8
Diadistis

Versuchte Folgendes und es funktionierte auch mit Krawatten.

SELECT rs.Field1,rs.Field2 
FROM (
    SELECT Field1,Field2, ROW_NUMBER() 
      OVER (Partition BY Section
            ORDER BY RankCriteria DESC ) AS Rank
    FROM table
    ) rs WHERE Rank <= 10
6
Raghu S

Könnte der Operator UNION für Sie arbeiten? Haben Sie ein SELECT für jeden Abschnitt, und verbinden Sie sie dann miteinander. Ich schätze, es würde nur für eine feste Anzahl von Abschnitten funktionieren.

4
sblundy

F) Suchen von TOP X-Datensätzen aus jeder Gruppe (Oracle)

SQL> select * from emp e 
  2  where e.empno in (select d.empno from emp d 
  3  where d.deptno=e.deptno and rownum<3)
  4  order by deptno
  5  ;

 EMPNO ENAME      JOB              MGR HIREDATE         SAL       COMM     DEPTNO

  7782 CLARK      MANAGER         7839 09-JUN-81       2450                    10
  7839 KING       PRESIDENT            17-NOV-81       5000                    10
  7369 SMITH      CLERK           7902 17-DEC-80        800                    20
  7566 JONES      MANAGER         7839 02-APR-81       2975                    20
  7499 ALLEN      SALESMAN        7698 20-FEB-81       1600        300         30
  7521 WARD       SALESMAN        7698 22-FEB-81       1250        500         30

6 Zeilen ausgewählt.


4
bharathreddy

Wenn Sie eine Ausgabe nach Abschnitten gruppieren möchten, werden nur die obersten n Datensätze aus den einzelnen Abschnitten angezeigt.

SECTION     SUBSECTION

deer        American Elk/Wapiti
deer        Chinese Water Deer
dog         Cocker Spaniel
dog         German Shephard
horse       Appaloosa
horse       Morgan

... dann sollte das Folgende ziemlich allgemein mit allen SQL-Datenbanken funktionieren. Wenn Sie die Top 10 haben möchten, ändern Sie die 2 gegen Ende der Abfrage in eine 10.

select
    x1.section
    , x1.subsection
from example x1
where
    (
    select count(*)
    from example x2
    where x2.section = x1.section
    and x2.subsection <= x1.subsection
    ) <= 2
order by section, subsection;

So richten Sie ein:

create table example ( id int, section varchar(25), subsection varchar(25) );

insert into example select 0, 'dog', 'Labrador Retriever';
insert into example select 1, 'deer', 'Whitetail';
insert into example select 2, 'horse', 'Morgan';
insert into example select 3, 'horse', 'Tarpan';
insert into example select 4, 'deer', 'Row';
insert into example select 5, 'horse', 'Appaloosa';
insert into example select 6, 'dog', 'German Shephard';
insert into example select 7, 'horse', 'Thoroughbred';
insert into example select 8, 'dog', 'Mutt';
insert into example select 9, 'horse', 'Welara Pony';
insert into example select 10, 'dog', 'Cocker Spaniel';
insert into example select 11, 'deer', 'American Elk/Wapiti';
insert into example select 12, 'horse', 'Shetland Pony';
insert into example select 13, 'deer', 'Chinese Water Deer';
insert into example select 14, 'deer', 'Fallow';
3
Craig

Während die Frage sich auf SQL Server 2005 bezog, sind die meisten Leute weitergegangen. Wenn sie diese Frage finden, ist die bevorzugte Antwort in anderen Situationen eine mit CROSS APPLY wie in diesem Blogbeitrag dargestellt .

SELECT *
FROM t
CROSS APPLY (
  SELECT TOP 10 u.*
  FROM u
  WHERE u.t_id = t.t_id
  ORDER BY u.something DESC
) u

Diese Abfrage umfasst 2 Tabellen. Die OP-Abfrage umfasst nur eine Tabelle, in denen eine auf Fensterfunktionen basierende Lösung möglicherweise effizienter ist.

2
Lukas Eder

Sie können diesen Ansatz ausprobieren. Diese Abfrage gibt 10 am dichtesten besiedelte Städte für jedes Land zurück.

   SELECT city, country, population
   FROM
   (SELECT city, country, population, 
   @country_rank := IF(@current_country = country, @country_rank + 1, 1) AS country_rank,
   @current_country := country 
   FROM cities
   ORDER BY country, population DESC
   ) ranked
   WHERE country_rank <= 10;
1
Ali