2014-08-30 6 views
-1

У нас есть таблица вроде следующегоПрисвоение номера группы на основе состояния

enter image description here

и мы хотим, чтобы написать запрос с генерируемой ID группы (на основе следующих)

Если страна имеет более одного элемента с той же категорией, что и записи группы [страны, категории] должны быть назначены с уникальным идентификатором группы,

поэтому для приведенной выше таблицы нам нужно написать один запрос (без хранимой процедуры или функция), который вернет результат, как показано ниже.

enter image description here

Мы попробовали запрос и его внешний вид, как очень сложные и не читаемые.

Так что мы ищем лучший запрос для достижения того же.

Спасибо заранее

+2

Использование SQL Server? Теги с двумя разными dbs. –

+0

Kinda выглядит как Access ... – vol7ron

ответ

2

Предполагая, что SQL Server, вы можете сделать это путем добавления OVER() к COUNT() и используя CASE заявления с DENSE_RANK():

;with cte AS (SELECT *,COUNT(*) OVER(PARTITION BY Country,Category) CT 
         ,CASE WHEN Category IS NOT NULL THEN DENSE_RANK() OVER (ORDER BY Country) END Rank_ 
       FROM Table1) 
SELECT Country 
     ,State 
     ,Category 
     ,CASE WHEN CT > 1 AND Rank_ IS NOT NULL THEN DENSE_Rank() OVER(ORDER BY Rank_ DESC) END AS Group_ 
FROM cte 
ORDER BY Country DESC,State 

Демо: SQL Fiddle

Только если вы заботиться о том, чтобы его пронумеровали от 1-n, вам нужно больше одного DENSE_RANK().

+0

Идеально подходит для решения, которое ищет, все еще его большой sql для моего дела. Но это более читаемо и легко поддерживать. Большое вам спасибо –

0

Вы можете сделать это в SQL Server как:

select t.*, cs.groupnum 
from table t left outer join 
    (select country, category, count(*) as cnt, 
      dense_rank() over (order by country, category) as groupnum 
     from table t 
     group by country, category 
     having count(*) > 1 
    ) cs 
    on t.country = cs.country and t.category = cs.category; 

В MySQL, вы можете сделать вариант на этом, используя переменные вместо dense_rank().

1

Если вы используете MySQL вы можете использовать следующее:

Fiddle:http://sqlfiddle.com/#!2/0f381/7/0

select t.country, t.state, t.category, v.grp 
    from (select x.*, @r := @r + 1 as grp 
      from (select country, category 
        from tbl 
       where category is not null 
       group by country, category 
       having count(*) > 1 
       order by category, state, country) x 
     cross join (select @r := 0) r) v 
right join tbl t 
    on v.country = t.country 
    and v.category = t.category 
+0

Это тоже работает. Спасибо. –

0
DROP TABLE #TEST 

GO 

CREATE TABLE #Test(
    Country NVARCHAR(100) 
    ,[State] NVARCHAR(100) 
    ,Category NVARCHAR(100) 
    ,GroupID INT); 

GO 

INSERT INTO #Test 
    (Country, State, Category) 
VALUES 
    ('US','AZ','G1'), 
    ('US','AL','G1'), 
    ('US','NY',null), 
    ('UK','TN','G1'), 
    ('UK','MH','G1'), 
    ('UK','AP','G3'), 
    ('CA','MI',null), 
    ('CA','CA',null); 


UPDATE 
    T2 
SET 
    T2.GroupID = T.RANKED_ID 
FROM 
    (SELECT COUNT(*) 'Count' 
      ,Country 
      ,Category 
      ,DENSE_RANK() OVER (ORDER BY Country DESC) AS Ranked_ID 
     FROM #Test 
     WHERE Category IS NOT NULL 
     GROUP BY Country, Category 
     HAVING COUNT(*) > 1 
    ) AS T 
    JOIN #Test T2 
    ON T.Category = T2.Category 
    AND T.Country = T2.Country 


SELECT * 
FROM #TEST 
Смежные вопросы