2015-12-27 3 views
1

Поэтому мне нужно выбрать набор идентификаторов документов и значение из таблицы, а затем дать вес для каждого из них в зависимости от значения. Она работает следующим образом:Выбор уникальных записей из таблицы и предоставление веса для повторений

Say таблица имеет значения:

DocID Value 
    1  1 
    1  1 
    2  1 
    2  2 

Выбрать, подберет каждый уникальный DocID, а затем дать ему значение веса. Документ с тем же значением, который повторяется дважды, будет иметь меньший вес, чем документ с двумя разными значениями. Так выход будет что-то вроде этого:

DocID Weight 
    1  1.5 
    2  2 

Итак, как вы видите, так как документ 1 имеет значение 1 повторяется два раза будет иметь начальный +1 к весу от первого значения, а затем +0,5, поскольку она повторяется один раз (снова получит +0.5, если значение повторится больше). Тогда Документ 2 имеет вес 2, так как значение 1 появляется один раз (+1), а значение 2 появляется один раз (+2)

Любая помощь будет высоко оценена.

ответ

2

Сначала агрегируйте данные, чтобы получить количество на документ/значение. Тогда, если я понимаю логику правильно, остальное просто агрегация дополнения:

select docid, 
     sum(case when cnt > 1 then 1 + 0.5 * (cnt - 1) else 0 end) 
from (select docid, value, count(*) as cnt 
     from t 
     group by docid, value 
    ) dv 
group by docid; 

На самом деле, я думаю, что внешний запрос может быть упрощен:

select docid, 
     0.5 + 0.5 * sum(cnt) 

И, все это может быть выражено count(distinct):

select docid, 
     (0.5 * count(distinct value) + 
     0.5 * count(*) 
     ) 
from t 
group by docid; 
+0

Упрощенная версия помогла вам, спасибо. –

0

Попробуйте это,

declare @t table(DocID int, Value int) 
insert into @t values 
(1, 1) 
,(1, 1) 
,(2, 1) 
,(2, 2) 
; 

WITH CTE 
AS (
    SELECT docid 
     ,value 
     ,ROW_NUMBER() OVER (
      PARTITION BY docid ORDER BY docid 
      ) rownum 
    FROM @t 
    ) 
    ,CTE1 
AS (
    SELECT docid 
     ,value 
     ,rownum 
     ,1.00 wtg 
    FROM cte 
    WHERE rownum = 1 

    UNION ALL 

    SELECT a.docid 
     ,b.value 
     ,b.rownum + 1 
     ,CASE 
      WHEN a.Value = b.value 
       THEN 0.50 
      ELSE 1 
      END 
    FROM CTE A 
    INNER JOIN cte1 B ON a.docid = b.DocID 
     AND A.rownum > b.rownum 
    ) 
SELECT docid 
    ,SUM(wtg) wtg 
FROM cte1 
GROUP BY docid 
Смежные вопросы