通过首字母将名称列表分区到文件夹中

时间:2011-05-07 18:35:18

标签: sql tsql ranking-functions

给出一组数据:

id    Name
   1  Aaa
   2  Aab
   3  AAc
…
 999  Zzz

,我想创建用初始字母对其进行分区的虚拟文件夹。例如,我想将7传递给函数并获取7个文件夹,例如:

  • A-C
  • d-F
  • 我-M
  • Ñ-Q
  • R-S
  • T-ż

...每个都包含相应的值(例如T-Z将包含Zzz)。我已经发现我可以使用NTILE()来获得相当接近的结果:

WITH Ntiles(Name, Ntile) AS (
    SELECT Name, NTILE(7) OVER(ORDER BY Name) FROM #Projects
)
SELECT MIN(LEFT(N.Name, 1)) + '-' + MAX(LEFT(N.Name, 1))
FROM Ntiles N 
GROUP BY Ntile

要添加所需的值,我正在做另外两个连接:

WITH Ntiles(Name, Ntile) AS (
    SELECT Name, NTILE(7) OVER(ORDER BY Name) FROM #Projects
) SELECT P.Name, (
    SELECT MIN(LEFT(N1.Name, 1)) + '-' + MAX(LEFT(N1.Name, 1)) FROM Ntiles N1 
    WHERE N1.Ntile = N2.Ntile
GROUP BY N1.Ntile
) FROM #Projects P INNER JOIN Ntiles N2 ON P.Name = N2.Name

......这似乎有点低效。

但这也是错误的:有重叠(例如,PJ-P中都出现了P-T字母。

我是否在正确的轨道上?有更有效的方法吗?如何防止重叠?

1 个答案:

答案 0 :(得分:2)

如果您只是需要将首字母列表分成相当相同的组,那么您应该大致按照您现在的方式进行,但顺序略有不同:

  1. 获取表格中的所有首字母。

  2. NTILE结果列表。

  3. 对NTILEd结果集进行分组。

  4. WITH letters AS (
      SELECT
        Letter = LEFT(Name, 1)
      FROM #Projects
      GROUP BY LEFT(Name, 1)
    ),
    ntiled AS (
      SELECT
        Letter,
        Folder = NTILE(7) OVER (ORDER BY Letter)
      FROM letters
    )
    SELECT
      Folder,
      FolderCaption = MIN(Letter) + '-' + MAX(Letter)
    FROM ntiled
    GROUP BY Folder