[SQL] 그룹화 순서 열 값의 변화에 의해 데이터 그룹
SQL그룹화 순서 열 값의 변화에 의해 데이터 그룹
다음과 같은 데이터로
create table #ph (product int, [date] date, price int)
insert into #ph select 1, '20120101', 1
insert into #ph select 1, '20120102', 1
insert into #ph select 1, '20120103', 1
insert into #ph select 1, '20120104', 1
insert into #ph select 1, '20120105', 2
insert into #ph select 1, '20120106', 2
insert into #ph select 1, '20120107', 2
insert into #ph select 1, '20120108', 2
insert into #ph select 1, '20120109', 1
insert into #ph select 1, '20120110', 1
insert into #ph select 1, '20120111', 1
insert into #ph select 1, '20120112', 1
나는 다음과 같은 출력을 생성하고 싶습니다 :
product | date_from | date_to | price
1 | 20120101 | 20120105 | 1
1 | 20120105 | 20120109 | 2
1 | 20120109 | 20120112 | 1
I 가격 그룹은 최대 및 최소 날짜를 보여 주면 나는 내가 원하는되지 않은 것을 다음 (날짜의 래핑을 통해 참조) 얻을 것이다.
product | date_from | date_to | price
1 | 20120101 | 20120112 | 1
1 | 20120105 | 20120108 | 2
그래서 기본적으로 내가 뭘 찾고있어 그룹 열 제품과 가격에 따라 데이터의 단계 변화에 의해 그룹입니다.
이를 달성하기 위해 가장 깨끗한 방법은 무엇입니까?
해결법
-
==============================
1.) (이 같은 전화를 두 ROW_NUMBER와 관련된 이러한 문제를 해결하는 (다소) 알려진 기술이있다 :
) (이 같은 전화를 두 ROW_NUMBER와 관련된 이러한 문제를 해결하는 (다소) 알려진 기술이있다 :
WITH marked AS ( SELECT *, grp = ROW_NUMBER() OVER (PARTITION BY product ORDER BY date) - ROW_NUMBER() OVER (PARTITION BY product, price ORDER BY date) FROM #ph ) SELECT product, date_from = MIN(date), date_to = MAX(date), price FROM marked GROUP BY product, price, grp ORDER BY product, MIN(date)
산출:
product date_from date_to price ------- ---------- ------------- ----- 1 2012-01-01 2012-01-04 1 1 2012-01-05 2012-01-08 2 1 2012-01-09 2012-01-12 1
-
==============================
2.나는이 포럼에 새로 온 사람은 나의 기여 도움이되기를 바랍니다.
나는이 포럼에 새로 온 사람은 나의 기여 도움이되기를 바랍니다.
당신이 정말로 (아마 가장 좋은 방법을 먹으 렴 생각하지만)을 CTE를 사용하지 않을 경우 당신은 세트 기반 코드를 사용하여 솔루션을 얻을 수 있습니다. 이 코드의 성능을 테스트해야합니다!
나는 각 레코드에 대한 고유 식별자를 사용할 수 있도록 나는 여분의 임시 테이블에 추가 한하지만 난 당신이 이미 소스 테이블이 열을해야합니다 생각한다. 그래서 임시 테이블을 heres.
If Exists (SELECT Name FROM tempdb.sys.tables WHERE name LIKE '#phwithId%') DROP TABLE #phwithId CREATE TABLE #phwithId ( SaleId INT , ProductID INT , Price Money , SaleDate Date ) INSERT INTO #phwithId SELECT row_number() over(partition by product order by [date] asc) as SalesId, Product, Price, Date FROM ph
선택 문 이제 본체
SELECT productId , date_from , date_to , Price FROM ( SELECT dfr.ProductId , ROW_NUMBER() OVER (PARTITION BY ProductId ORDER BY ChangeDate) AS rowno1 , ChangeDate AS date_from , dfr.Price FROM ( SELECT sl1.ProductId AS ProductId , sl1.SaleDate AS ChangeDate , sl1.price FROM #phwithId sl1 LEFT JOIN #phwithId sl2 ON sl1.SaleId = sl2.SaleId + 1 WHERE sl1.Price <> sl2.Price OR sl2.Price IS NULL ) dfr ) da1 LEFT JOIN ( SELECT ROW_NUMBER() OVER (PARTITION BY ProductId ORDER BY ChangeDate) AS rowno2 , ChangeDate AS date_to FROM ( SELECT sl1.ProductId , sl1.SaleDate AS ChangeDate FROM #phwithId sl1 LEFT JOIN #phwithId sl3 ON sl1.SaleId = sl3.SaleId - 1 WHERE sl1.Price <> sl3.Price OR sl3.Price IS NULL ) dto ) da2 ON da1.rowno1 = da2.rowno2
가격 버킷이 변경 될 때 한 기록에 의해 상쇄 데이터 소스를 결합하여 (+ 또는 -) 우리는 식별 할 수있는 다음 버킷의 시작 및 종료 날짜를 받고 자사의 단지 문제는 단일 레코드로 백업 할 수 있습니다.
모두는 가로장 설치 등등 비트와 나는 그것의 더 나은 성능을 제공 할 것 확실하지 않다 그러나 나는 도전을 즐겼다.
-
==============================
3.
WITH marked AS ( SELECT *, case when (lag(price,1,'') over (partition by product order by date_from)) = price then 0 else 1 end is_price_change FROM #ph ), marked_as_group AS ( SELECT m.*, SUM(is_price_change) over (PARTITION BY product order by date_from ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS price_change_group FROM marked m ), SELECT product, date_from = MIN(date_from), date_to = MAX(date_to), price = MIN(price) FROM marked_as_group GROUP BY product, price_change_group ORDER BY product, date_to
-
==============================
4.내가있는쪽으로 와서 하나 개의 솔루션은 상대적으로 "깨끗한"입니다 :
내가있는쪽으로 와서 하나 개의 솔루션은 상대적으로 "깨끗한"입니다 :
;with cte_sort (product, [date], price, [row]) as (select product, [date], price, row_number() over(partition by product order by [date] asc) as row from #ph) select a.product, a.[date] as date_from, c.[date] as date_to, a.price from cte_sort a left outer join cte_sort b on a.product = b.product and (a.row+1) = b.row and a.price = b.price outer apply (select top 1 [date] from cte_sort z where z.product = a.product and z.row > a.row order by z.row) c where b.row is null order by a.[date]
당신이 다음 DATEADD 같은 기능을 사용하는 경우 어떤 날짜가 누락 여부에 대해 걱정할 필요가 없습니다 때문에 ROW_NUMBER와 CTE를 사용했다. 당신은 분명히 단지 당신이 (내가)이 DATE_TO 열이하고 싶은 경우에 적용되는 외부가 필요합니다.
이 솔루션은 내가 그러나 내가 5 백만 행 내 테이블에 원하는대로 빨리 수행하기 위해 점점 약간의 문제가 발생하고, 내 문제를 해결 않습니다.
-
==============================
5.
Create function [dbo].[AF_TableColumns](@table_name nvarchar(55)) returns nvarchar(4000) as begin declare @str nvarchar(4000) select @str = cast(rtrim(ltrim(column_name)) as nvarchar(500)) + coalesce(' ' + @str , ' ') from information_schema.columns where table_name = @table_name group by table_name, column_name, ordinal_position order by ordinal_position DESC return @str end --select dbo.AF_TableColumns('YourTable') Select * from YourTable
from https://stackoverflow.com/questions/10110026/group-data-by-the-change-of-grouping-column-value-in-order by cc-by-sa and MIT license
'SQL' 카테고리의 다른 글
[SQL] 트리거 오류 : 현재 트랜잭션은 커밋 할 수 없습니다 및 운영을 지원하지 수있는 로그 파일에 쓰기 (0) | 2020.06.29 |
---|---|
[SQL] C #에서 SQL 서버에서 VARBINARY 데이터를 스트리밍 (0) | 2020.06.29 |
[SQL] SQL DATEDIFF - 행 사이 DATEDIFF를 찾을 수 (0) | 2020.06.29 |
[SQL] ( "LIKE"및 "="비교) REGEXP 성능 (0) | 2020.06.29 |
[SQL] PHP : 단일 쿼리에서 업데이트 여러 MySQL의 필드 (0) | 2020.06.29 |