仅转置 SQL 中的某些数据



我的数据如下所示:

Company Year         Total   Comment                 
Comp A  01-01-2000   5,000   Checked
Comp A  01-01-2001   6,000   Checked
Comp B  05-05-2007   3,000   Not checked completely
Comp B  05-05-2008   4,000   Checked
Comp C  18-01-2003   1,500   Not checked completely
Comp C  18-01-2002   3,500   Not checked completely

我被要求转置某些数据,但我不相信这可以使用 SQL(服务器)来完成,因此它看起来像这样:

Company     Base Date   Base Date-1   Comment Base Date      Comment Base Date-1
Comp A      01-01-2001  01-01-2000    Checked                Checked
Comp B      05-05-2008  05-05-2007    Checked                Not completely checked
Comp C      18-01-2003  18-01-2002    Not completely checked Not completely checked

我从来没有建造过这样的东西。如果我愿意,那么也许 Excel 是更好的选择?我应该如何解决这个问题?

是否可以使用选择最大(基准日期)和最小(基准日期)?然后我该如何像那样处理琴弦..

您可以使用self join来执行此操作。但是,您应该考虑像 2 月 29 日这样的日期,因为它们只出现在闰年。

select t1.company,t1.year as basedate,t2.year as basedate_1,
t1.comment as comment_basedate,t2.comment as comment_basedate_1
from t t1
left join t t2 on t1.company=t2.company dateadd(year,1,t2.year)=t1.year

如果只需要公司两个日期值都存在的结果,请将left join更改为inner join。此解决方案假定每天只能有一个注释。

我会通过公共表表达式中的分析函数为按公司按年份划分的每条记录分配一个行号......然后使用左自联...在行号 + 1 和公司上。

这假设您只需要每个公司使用 2 最近 2 年的 1 条记录。 如果公司仅存在 1 条记录,则第二年可以接受 null 值。 如果没有,我们可以将左连接更改为内部连接并消除两个记录......

我们使用通用表表达式(尽管内联视图也可以)为每条记录分配行号。 然后,该值在我们的自联接中可用,因此我们不必担心不同的日期和最大值。 然后,我们使用我们的行号(RN)和公司将2个所需的记录连接在一起。 为了节省一些性能,我们将 1 个表限制为 RN 1,将第二个表限制为 RN 2。

WITH CTE AS (
SELECT *, Row_Number() over (Partition by Company Order by Year Desc) RN FROM TABLE)
SELECT A.Company
, A.Year as Base_Date
, B.Year as Base_Date1
, A.comment as Base_Date_Comment
, B.Comment as Base_Date1_Comment
FROM CTE A
LEFT JOIN CTE  B
on A.RN+1 = B.RN
and A.Company = B.Company
and B.RN = 2
WHERE A.RN = 1 

请注意,RN=2 的限制必须在联接上,因为它是外联接,否则我们将在没有 2 年的情况下淘汰这些公司。(实质上是让左派加入内在)

此方法使数据的所有列可用于每一行。

如果每行只有两行,那么这很简单。 如果有超过两行,你可以做这样的事情 - 基本上连接所有行,然后确保A代表最早的行,B代表最新的行。

SELECT A.Company, A.Year AS [Base Date], B.Year  AS [Base Date 1],
A.Comment AS [Comment Base Date], B.Comment AS [Comment Base Date 1]
FROM MyTable A
INNER JOIN MyTable B ON A.Company = B.Company
WHERE A.Year = (SELECT MIN(C.YEAR) FROM MyTable C WHERE C.Company = A.Company)
AND B.Year = (SELECT MAX(C.YEAR) FROM MyTable C WHERE C.Company = B.Company)

可能有更有效的方法可以使用Row_Number或其他东西来做到这一点。

最新更新