根据条件分配组号

时间:2014-08-30 00:06:11

标签: mysql sql sql-server

我们有一个如下表格

enter image description here

我们想要编写一个带有生成的组ID的查询(基于以下内容)

如果某个国家/地区的商品具有相同类别的商品数超过1个,则应为[国家/地区,类别]组记录分配唯一的组ID

因此,对于上表,我们需要编写单个查询(没有存储过程或函数),这将返回如下所示的结果。

enter image description here

我们尝试了查询,看起来非常复杂且无法读取。

所以我们正在寻找更好的查询来实现同样的目标。

提前谢谢

4 个答案:

答案 0 :(得分: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()

答案 1 :(得分:1)

如果您使用的是MySQL,则可以使用以下内容:

小提琴: 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

答案 2 :(得分: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()来对此进行变体。

答案 3 :(得分: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