하나의 쿼리로 각 섹션에서 상위 10 개의 레코드를 반환하고 싶습니다. 누구나 그것을하는 방법을 도울 수 있습니까? 섹션은 테이블의 열 중 하나입니다.
데이터베이스는 SQL Server 2005입니다. 입력 한 날짜별로 상위 10 개를 반환하려고합니다. 섹션은 비즈니스, 지역 및 기능입니다. 특정 날짜의 경우 상위 10 개 비즈니스 행 (가장 최근 항목), 상위 10 개 로컬 행 및 상위 10 개 기능 만 원합니다.
하나의 쿼리로 각 섹션에서 상위 10 개의 레코드를 반환하고 싶습니다. 누구나 그것을하는 방법을 도울 수 있습니까? 섹션은 테이블의 열 중 하나입니다.
데이터베이스는 SQL Server 2005입니다. 입력 한 날짜별로 상위 10 개를 반환하려고합니다. 섹션은 비즈니스, 지역 및 기능입니다. 특정 날짜의 경우 상위 10 개 비즈니스 행 (가장 최근 항목), 상위 10 개 로컬 행 및 상위 10 개 기능 만 원합니다.
답변:
SQL 2005를 사용하는 경우 다음과 같이 할 수 있습니다 ...
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
RankCriteria에 관계가 있으면 10 개가 넘는 행을 반환 할 수 있으며 Matt의 솔루션이 더 나을 수 있습니다.
DENSE_RANK
번호 매기기에 공백이없는 것으로 끝났습니다 . +1
T-SQL에서는 다음을 수행합니다.
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
ROW_NUMBER
함수를 구현하는 모든 데이터베이스에서 작동합니다. 예를 들어, SQLite에서이 솔루션을 사용했습니다.
이것은 SQL Server 2005에서 작동합니다 (설명을 반영하도록 편집 됨).
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
나는 이것을 이렇게한다 :
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;
업데이트 : 이 GROUP BY 예제는 MySQL 및 SQLite에서만 작동합니다. 데이터베이스는 GROUP BY에 관한 표준 SQL보다 더 관대합니다. 대부분의 SQL 구현에서는 집계 표현식의 일부가 아닌 선택 목록의 모든 열도 GROUP BY에 있어야합니다.
SQL Server> = 2005를 사용하면 한 번의 선택 만으로 작업을 해결할 수 있습니다 .
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;
top 1
작동 하는지 설명 할 수 있습니까? case
order by
섹션이 무엇인지 아는 경우 다음을 수행 할 수 있습니다.
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
이 스레드가 조금 오래되었다는 것을 알고 있지만 비슷한 문제가 발생했습니다 (각 범주에서 최신 기사를 선택하십시오). 이것은 내가 생각해 낸 해결책입니다.
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
이것은 Darrel의 솔루션과 매우 유사하지만 의도 한 것보다 많은 행을 리턴 할 수있는 RANK 문제를 극복합니다.
JOIN
대신를 사용하여 최적화 할 수 있습니다 . LEFT JOIN
TopCategoryArticles
Article
섹션별로 그룹화 된 출력을 생성하려면 다음과 같이 각 섹션에서 최상위 n 개의 레코드 만 표시 하십시오.
SECTION SUBSECTION
deer American Elk/Wapiti
deer Chinese Water Deer
dog Cocker Spaniel
dog German Shephard
horse Appaloosa
horse Morgan
... 다음은 모든 SQL 데이터베이스에서 일반적으로 작동합니다. 상위 10 개를 원하면 쿼리 끝쪽으로 2를 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;
설정하기:
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';
Q) 각 그룹 (Oracle)에서 TOP X 레코드 찾기
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 개 행이 선택되었습니다.
질문은 SQL Server 2005에 관한 것이었지만 대부분의 사람들이이 질문을 찾았다면 다른 상황에서 선호되는 답변 은이 블로그 게시물에 설명 된대로 사용 CROSS APPLY
하는 것입니다 .
SELECT *
FROM t
CROSS APPLY (
SELECT TOP 10 u.*
FROM u
WHERE u.t_id = t.t_id
ORDER BY u.something DESC
) u
이 쿼리에는 2 개의 테이블이 포함됩니다. OP의 쿼리에는 1 개의 테이블 만 포함되며,이 경우 창 함수 기반 솔루션이 더 효율적일 수 있습니다.
이 방법을 시도해 볼 수 있습니다. 이 쿼리는 각 국가에서 가장 인구가 많은 도시 10 개를 반환합니다.
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;