SQL如何使列值向右或向左滑动?
How do you make a column value slide to the right or the left using SQL?
这是一道面试题。
如果我有这样的table:
ID FirstName LastName
-- --------- --------
1 Aaron Aames
2 Malcolm Middle
3 Zamon Zorr
我怎样才能得到这样的输出?
Aaron Aames
Aames Malcolm
Malcolm Middle
Middle Zamon
Zamon Zorr
注意:如果您需要特定的方言,请使用 T-SQL。
你的声望很高,所以这不只是一个"they asked me at an interview"类的问题。
有几种方法。我认为我会选择 union all
。认识到每隔一行来自 table。其余的是从一行到另一行。所以,这表明:
select firstname, lastname
from likethis t
union all
select t.lastname, lead(t.firstname) over (order by id)
from likethis t
唉,这给你六行而不是五行,所以最后一行需要被过滤掉:
select firstname, lastname
from (select firstname, lastname
from likethis t
union all
select t.lastname, lead(t.firstname) over (order by id)
from likethis t
) t
where lastname is not null
order by firstname;
注意:我无法确定排序标准是按字母顺序还是按 id;这些解决方案假定它是按字母顺序排列的。
第二个注意事项:我猜这不是他们想要的解决方案。他们可能正在寻找自我加入。但是,当 lead()
为您完成工作时,为什么还要麻烦。
这是使用自连接的另一种方法。
CREATE TABLE temp (ID INT IDENTITY, FirstName VARCHAR(25), LastName VARCHAR(25));
INSERT INTO temp VALUES
(N'Aaron', N'Aames'),
(N'Malcolm', N'Middle'),
(N'Zamon', N'Zorr');
WITH names(ID, Name, ColNum) AS(
SELECT
ID, FirstName, 1
FROM temp
UNION ALL
SELECT
ID, LastName, 2
FROM temp
),
numbered AS(
SELECT
rn = ROW_NUMBER() OVER(ORDER BY ID, ColNum),
Name
FROM names
)
SELECT
n.Name AS Name1, n2.Name AS Name2
FROM numbered n
INNER JOIN numbered n2
ON n.rn = n2.rn - 1
DROP TABLE temp
我觉得可以这样解决:
SELECT
t.LastName AS FirstName, t2.FirstName AS LastName
FROM
t
INNER JOIN t as t2 ON t2.ID - 1 = t.ID
UNION
SELECT
t3.FirstName, t3.LastName
FROM t AS t3
据我检查正确,它应该按以下方式提供最终结果集:
Aaron Aames <= originates from t3: where t3.ID = 1
Aames Malcolm <= originates from (t1, t2) Join: where t2.ID = 2 and t.ID = 1
Malcolm Middle <= originates from t3: where t3.ID = 2
Middle Zamon <= originates from (t1, t2) Join: where t2.ID = 3 and t.ID = 2
Zamon Zorr <= originates from t3: where t3.ID = 3
这是一道面试题。
如果我有这样的table:
ID FirstName LastName
-- --------- --------
1 Aaron Aames
2 Malcolm Middle
3 Zamon Zorr
我怎样才能得到这样的输出?
Aaron Aames
Aames Malcolm
Malcolm Middle
Middle Zamon
Zamon Zorr
注意:如果您需要特定的方言,请使用 T-SQL。
你的声望很高,所以这不只是一个"they asked me at an interview"类的问题。
有几种方法。我认为我会选择 union all
。认识到每隔一行来自 table。其余的是从一行到另一行。所以,这表明:
select firstname, lastname
from likethis t
union all
select t.lastname, lead(t.firstname) over (order by id)
from likethis t
唉,这给你六行而不是五行,所以最后一行需要被过滤掉:
select firstname, lastname
from (select firstname, lastname
from likethis t
union all
select t.lastname, lead(t.firstname) over (order by id)
from likethis t
) t
where lastname is not null
order by firstname;
注意:我无法确定排序标准是按字母顺序还是按 id;这些解决方案假定它是按字母顺序排列的。
第二个注意事项:我猜这不是他们想要的解决方案。他们可能正在寻找自我加入。但是,当 lead()
为您完成工作时,为什么还要麻烦。
这是使用自连接的另一种方法。
CREATE TABLE temp (ID INT IDENTITY, FirstName VARCHAR(25), LastName VARCHAR(25));
INSERT INTO temp VALUES
(N'Aaron', N'Aames'),
(N'Malcolm', N'Middle'),
(N'Zamon', N'Zorr');
WITH names(ID, Name, ColNum) AS(
SELECT
ID, FirstName, 1
FROM temp
UNION ALL
SELECT
ID, LastName, 2
FROM temp
),
numbered AS(
SELECT
rn = ROW_NUMBER() OVER(ORDER BY ID, ColNum),
Name
FROM names
)
SELECT
n.Name AS Name1, n2.Name AS Name2
FROM numbered n
INNER JOIN numbered n2
ON n.rn = n2.rn - 1
DROP TABLE temp
我觉得可以这样解决:
SELECT
t.LastName AS FirstName, t2.FirstName AS LastName
FROM
t
INNER JOIN t as t2 ON t2.ID - 1 = t.ID
UNION
SELECT
t3.FirstName, t3.LastName
FROM t AS t3
据我检查正确,它应该按以下方式提供最终结果集:
Aaron Aames <= originates from t3: where t3.ID = 1
Aames Malcolm <= originates from (t1, t2) Join: where t2.ID = 2 and t.ID = 1
Malcolm Middle <= originates from t3: where t3.ID = 2
Middle Zamon <= originates from (t1, t2) Join: where t2.ID = 3 and t.ID = 2
Zamon Zorr <= originates from t3: where t3.ID = 3