흥미로운 질문입니다! SQL Server에서이 문제를 해결할 방법을 찾은 것 같습니다. 그럼에도 불구하고 오히려 복잡 :
- 이었다 각 조합에 대해 1 씩 각
ids
- Increate의 occurance을 조합 목록을 만들 조합에게
- 전화 저장 프로 시저를 계산하는 저장 프로 시저를 만들기 이전에
발견 결과 테이블에
- 삽입 새로운 조합
여기에 전체 코드는 다음과 같습니다
귀하의 예제 데이터 세트에 대한
set nocount on
-- Helper table for sp_Combinations
if OBJECT_ID('tempdb..#combos') is not null
drop table #combos
create table #combos (
comboid int default 1,
basecomboid int,
combosize int default 1,
val int,
primary key (comboid, val))
if OBJECT_ID('dbo.sp_Combinations') is null
exec ('create procedure dbo.sp_Combinations as select 1')
go
-- Creates a list of all combinations of values in #combos,
-- based on a starting list with comboid = 1
alter procedure dbo.sp_Combinations
as begin
delete from #combos where comboid <> 1
declare @n int
select @n = count(*) from #combos
update #combos set combosize = (select count(*) from #combos)
if @n = 1
return
-- Add individual numbers
insert #combos
(comboid, basecomboid, val)
select row_number() over (order by val) + 1
, 1
, val
from #combos
where comboid = 1
declare @k int
set @k = 1
while @k + 1 < @n
begin
declare @max_combo_id int
select @max_combo_id = max(comboid) from #combos
-- Add one new member to each combination of size @k
-- The new member must be larger than all existing members
-- F.e. for @n = 4 and @k = 1:
-- (1) --> (1,2) (1,3) (1,4)
-- (2) --> (2,3) (2,4)
-- (3) --> (3,4)
-- (4) --> no new combinations
;with b as (
select val
from #combos
where comboid = 1
), g as (
select comboid
, max(val) as maxval
from #combos c
where combosize = @k
group by
comboid
)
insert #combos (comboid, basecomboid, combosize, val)
select row_number() over (order by g.comboid) + @max_combo_id
, g.comboid
, @k + 1
, b.val
from b
join g
on b.val > g.maxval
-- Add the members of the base combo
insert #combos (comboid, basecomboid, combosize, val)
select l.comboid
, l.basecomboid
, l.combosize
, b.val
from #combos l
join #combos b
on b.comboid = l.basecomboid
where l.combosize = @k + 1
set @k = @k + 1
end
end
go
go
-- Input table
declare @t table (ids int, idk int)
insert into @t (ids, idk) values
(1, 2), (1, 3), (1, 4),
(2, 2), (2, 3), (2, 4),
(3, 2), (3, 5), (3, 4),
(4, 2), (4, 3);
-- Valid combinations with number of occurrences
declare @combinations table (comboid int, val int, cnt int)
-- Iterate over all ids
declare cur cursor for select distinct ids from @t
open cur
declare @ids int
while 1=1
begin
fetch from cur into @ids
if @@FETCH_STATUS <> 0
break
-- Calculate combinations for this ids
truncate table #combos
insert into #combos (comboid, val) select 1, idk from @t where ids = @ids
exec dbo.sp_Combinations
-- Increase count of existing combinations
update u
set cnt = cnt + 1
from @combinations u
where exists
(
select *
from @combinations a
full join
#combos b
on a.val = b.val
where a.comboid = u.comboid
group by
a.comboid
having max(case when a.val is null then 1 else 0 end) = 0
and max(case when b.val is null then 1 else 0 end) = 0
)
-- Insert new combinations
declare @max_combo_id int
select @max_combo_id = isnull(max(comboid),0) from @combinations
insert @combinations
(comboid, val, cnt)
select n.comboid + @max_combo_id
, n.val
, 1
from #combos n
where not exists
(
select *
from @combinations a
full join
#combos b
on a.val = b.val
where b.comboid = n.comboid
group by
b.comboid
having max(case when a.val is null then 1 else 0 end) = 0
and max(case when b.val is null then 1 else 0 end) = 0
)
end
close cur
deallocate cur
-- Display result
select x.r as combination
, cnt as occurrences
from (
select distinct comboid
, cnt
from @combinations
) a
cross apply
(
select val as [text()]
from @combinations c
where c.comboid = a.comboid
for xml path('')
) x(r)
where a.cnt > 1
order by
len(x.r) desc
, cnt desc
이 인쇄 :
combination occurrences
234 2
23 3
24 3
34 2
2 4
3 3
4 3
Vitalii은 - 당신이 IDK 값의 최대 #을 의미합니까? 예를 들어, 그가 2 idks의 일반적인 세트의 수를 찾고 있다면, 이것은 비교적 쉬울 것입니다. 일반적인 idk 2 개 또는 3 개를 찾는다면 여전히 가능합니다 (그러나 더 큰 데이터 세트 및 직선 SQL에서는 메모리 집약적입니다). – Andrew
이것은 프로그래밍 언어를 통한 사소한 문제이지만, 대부분의 데이터베이스에서 스트레이트 SQL에 대한 하드 (비효율적 인) 문제입니다 (제한되지 않은 idk 가정). SQL 만 사용할 수있는 경우 DBMS 내의 내장 프로 시저 논리를 활용하여 일부/모든 논리를 수행하는 것을 고려하십시오. – Andrew
그렇게하지 않겠습니다. 그것은 세트의 이론을 전문으로하는 일부 수학자가 대답 할 수있는 문제의 종류입니다. 나는 조합을 "평평하게"하려고 노력할 것입니다. 그러나 이들이 정수이기 때문에 조합 수는 모든 SQL에 비해 너무 큽니다. idks가 특정 범위 (예 : 1-9)에 있으면 나는 그 일을 할 수있는 SELECT 문을 쓰는 재미만을 위해서입니다. – hol