Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 如何设计从行创建动态列的查询_Sql_Sql Server_Sql Server 2005_Tsql_Sql Server 2008 - Fatal编程技术网

Sql 如何设计从行创建动态列的查询

Sql 如何设计从行创建动态列的查询,sql,sql-server,sql-server-2005,tsql,sql-server-2008,Sql,Sql Server,Sql Server 2005,Tsql,Sql Server 2008,我有数据 表1 ID Name ----------- 1 n1 2 n2 3 n4 表2 FID YearS Val ---------------------- 1 2008 Up 1 2009 Down 1 2010 Up 2 2000 Up 2 2001 Down 2 2002 Up 2 2003 Up 3 2009

我有数据

表1

ID     Name
-----------
1      n1
2      n2
3      n4
表2

FID   YearS    Val
----------------------
1     2008     Up
1     2009     Down
1     2010     Up
2     2000     Up
2     2001     Down
2     2002     Up
2     2003     Up
3     2009     Down
3     2010     Up
我想以以下格式返回数据:

ID  Yr1  Val1    Yr2   Val2  Yr3   Val3    Yr4  Val4
--------------------------------------------------------
1   2008 Up      2009  Down  2010  Up      NULL Null
2   2000 Up      2001  Down  2002  Up      2003 Up
3   2009 Down    2010  Up    NULL  NULL    NULL Null
根据ID的最大列数,我想创建列名,然后转换列中的行。使用sql查询可以做到这一点吗?

此查询应该会有所帮助

;WITH cte AS
    (
    SELECT *, ROW_NUMBER() OVER (PARTITION BY FID ORDER BY FID, YearS) AS NUMBER
    FROM Table2
    )

SELECT t.ID, MAX(CASE WHEN cte.number = 1 THEN cte.YearS END) as yr1, MAX(CASE WHEN cte.number = 1 THEN cte.Val END) as val1,
MAX(CASE WHEN cte.number = 2 THEN cte.YearS END) as yr2, MAX(CASE WHEN cte.number = 2 THEN cte.Val END) as val2,
MAX(CASE WHEN cte.number = 3 THEN cte.YearS END) as yr3, MAX(CASE WHEN cte.number = 3 THEN cte.Val END) as val3,
MAX(CASE WHEN cte.number = 4 THEN cte.YearS END) as yr4, MAX(CASE WHEN cte.number = 4 THEN cte.Val END) as val4
FROM Table1 T
JOIN cte ON t.ID = cte.FID
GROUP BY t.ID

请参阅:

我创建了一个名为“Table2”的表,其中包含您在上面的表2标题下显示的数据

下面是我在SQLServer2008中使用的SQL

WITH RankedValues AS
(
    SELECT
        FID AS ID,
        YearS,
        ROW_NUMBER() OVER(PARTITION BY FID ORDER BY YearS) AS YearSRank,
        Val
    FROM
        Table2
)
SELECT
    ID,
    MAX((CASE WHEN YearSRank = 1 THEN YearS ELSE 0 END)) AS Yr1,
    MAX((CASE WHEN YearSRank = 1 THEN Val ELSE '' END)) AS Val1,
    MAX((CASE WHEN YearSRank = 2 THEN YearS ELSE 0 END)) AS Yr2,
    MAX((CASE WHEN YearSRank = 2 THEN Val ELSE '' END)) AS Val2,
    MAX((CASE WHEN YearSRank = 3 THEN YearS ELSE 0 END)) AS Yr3,
    MAX((CASE WHEN YearSRank = 3 THEN Val ELSE '' END)) AS Val3,
    MAX((CASE WHEN YearSRank = 4 THEN YearS ELSE 0 END)) AS Yr4,
    MAX((CASE WHEN YearSRank = 4 THEN Val ELSE '' END)) AS Val4
FROM
    RankedValues
GROUP BY
    ID
上述SQL将导致以下情况:

ID   Yr1     Val1  Yr2     Val2    Yr3     Val3  Yr4     Val4
---------------------------------------------------------------------
1    2008    Up    2009    Down    2010    Up    0    
2    2000    Up    2001    Down    2002    Up    2003    Up
3    2009    Down  2010    Up      0             0    
之所以看不到
NULL
值,是因为每个
案例中的
ELSE
语句。 如果您希望使用
NULL
值,只需根据需要删除
ELSE 0
ELSE'

我现在不知道是否有可能使其通用,例如:处理未知数量的不同FID,因为这也意味着生成通用的列名(Yr1、al1、Yr2等)

您可以使用动态SQL实现这一点,但由于我不太喜欢动态SQL,所以我会尝试寻找另一种处理方法

--编辑(增加了完整性的轴心方法)

我查看了Joe Stefanelli发布的链接,并根据您的要求添加了下面的SQL。虽然我不喜欢动态SQL的概念,但在这个特定的实例中,我找不到任何其他方法

DECLARE @query VARCHAR(4000)
DECLARE @years VARCHAR(2000)

SELECT @years = STUFF((
    SELECT DISTINCT
        '],[' + ltrim(str(YearS))
    FROM Table2
    ORDER BY '],[' + ltrim(str(YearS))
    FOR XML PATH('')), 1, 2, '') + ']'

SET @query =
    'SELECT * FROM
    (
        SELECT FID AS ID,YearS,Val
        FROM Table2
    ) AS t
    PIVOT (MAX(Val) FOR YearS IN (' + @years + ')) AS pvt'

EXECUTE (@query)
这将导致以下结果:

ID  2000    2001    2002    2003    2008    2009    2010
---------------------------------------------------------
1   NULL    NULL    NULL    NULL    Up      Down    Up
2   Up      Down    Up      Up      NULL    NULL    NULL
3   NULL    NULL    NULL    NULL    NULL    Down    Up

根据您最喜欢的格式和方法,至少您有自己的选择。

使用报表生成器生成报表!有没有理由让你每年有两列,而不是把年份作为列的名称?是的,但我不确定会有多少年,我的列可以扩展到yr4之外,比如yr5、yr6、YR7。与行不同,SELECT子句中必须有定义的列数(这里我不会提到动态SQL)。您可以在此查询中添加更多列,当年份不存在时,将生成所有空值。我在处理我的查询时没有看到BOB的答案。基本上是一样的。我无意重复这个答案。