【问题标题】:Assigning group number based on condition根据条件分配组号
【发布时间】:2014-08-30 00:06:11
【问题描述】:

我们有一个如下表

我们想用生成的组 ID 编写一个查询(基于以下)

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

所以对于上表,我们需要编写一个查询(没有存储过程或函数),它将返回如下结果。

我们尝试了查询,它看起来非常复杂且不可读。

所以我们正在寻找更好的查询来达到同样的效果。

提前谢谢你

【问题讨论】:

  • 使用 SQL Server?标记有两个不同的数据库。
  • 有点像 Access...

标签: mysql sql sql-server


【解决方案1】:

假设 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()

【讨论】:

  • 非常适合我正在寻找的解决方案,对于我来说仍然是它的大 sql。但是这个更具可读性和易于维护。非常感谢
【解决方案2】:

如果您使用的是 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

【讨论】:

    【解决方案3】:

    您可以在 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() 对此进行变体。

    【讨论】:

      【解决方案4】:
      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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-29
        • 2015-11-19
        • 1970-01-01
        • 2018-04-30
        • 1970-01-01
        相关资源
        最近更新 更多