昨天在求职面试中,我被问到这个问题,我对此一无所知.假设我有一个单词"Manhattan"我想在SQL中只显示字母'M','A','N','H','T'.怎么做?任何帮助表示赞赏.
use*_*740 12
好吧,这是我的解决方案(sqlfiddle) - 它的目的是使用"关系SQL"操作,这可能是面试官在概念上的用途.
完成的大部分工作只是将字符串转换为一组(pos,letter)记录,因为相关的最终应用DQL仅仅是应用了分组和排序的SELECT.
select letter
from (
-- All of this just to get a set of (pos, letter)
select ns.n as pos, substring(ss.s, ns.n, 1) as letter
from (select 'MANHATTAN' as s) as ss
cross join (
-- Or use another form to create a "numbers table"
select n from (values (1),(2),(3),(4),(5),(6),(7),(8),(9)) as X(n)
) as ns
) as pairs
group by letter -- guarantees distinctness
order by min(pos) -- ensure output is ordered MANHT
Run Code Online (Sandbox Code Playgroud)
上述查询适用于SQL Server 2008,但可能必须为其他供应商更改"Numbers表".否则,没有使用特定于供应商的任何东西 - 没有CTE,或函数的交叉应用,或程序语言代码.
话虽如此,上面的内容是为了展示一种概念方法 - SQL被设计用于集合和关系以及跨记录的多重性; 在某种意义上,上述例子仅仅是对此类的歪曲.
检查中间关系,
select ns.n as pos, substring(ss.s, ns.n, 1) as letter
from (select 'MANHATTAN' as s) as ss
cross join (
select n from (values (1),(2),(3),(4),(5),(6),(7),(8),(9)) as X(n)
) as ns
Run Code Online (Sandbox Code Playgroud)
使用交叉连接生成字符串(1行)的笛卡尔积和数字(9行); substring然后将该函数与字符串和每个数字一起应用,以根据其位置获得每个字符.结果集包含记录 -
POS LETTER
1 M
2 A
3 N
..
9 N
Run Code Online (Sandbox Code Playgroud)
然后外部选择组根据字母记录每个记录,并且结果记录按建立分组的字母的最小(第一)发生位置排序.(没有字母的顺序会有所不同,但最终的顺序不会得到保证.)
一种方法(如果使用SQL Server)使用递归CTE(Commom Table Expression).
DECLARE @source nvarchar(100) = 'MANHATTAN'
;
WITH cte AS (
SELECT SUBSTRING(@source, 1, 1) AS c1, 1 as Pos
WHERE LEN(@source) > 0
UNION ALL
SELECT SUBSTRING(@source, Pos + 1, 1) AS c1, Pos + 1 as Pos
FROM cte
WHERE Pos < LEN(@source)
)
SELECT DISTINCT c1 from cte
Run Code Online (Sandbox Code Playgroud)
SqlFiddle就在这里.我不得不内联@source为SqlFiddle,但上面的代码在Sql Server中工作正常.
第一SELECT行生成初始行(在本例中为"M",1).第二个SELECT是生成后续行的递归部分,Pos每次都会增加列,直到WHERE Pos < LEN(@source)最终满足终止条件.最终选择删除重复项.在内部,SELECT DISTINCT对行进行排序以便于删除重复项,这就是为什么最终输出恰好按字母顺序排列的原因.由于您没有将订单指定为要求,因此我将其保留为原样.但是你可以修改它以使用一个GROUP代替,MIN(Pos)如果你需要输出字符的原始顺序,那就命令.
同样的技术可以用于生成字符串的所有Bigrams之类的事情,只需对上面的一般结构进行一些小改动.
| 归档时间: |
|
| 查看次数: |
2335 次 |
| 最近记录: |