试图从表中获得比实际存在更多的行

时间:2017-07-11 12:32:25

标签: sql sql-server

我不确定这个问题的描述性标题所以我把它放在那里我认为是最好的句子。

我有一张这样的表:

SQL query Union All

我想在不使用游标的情况下编写SQL语句来返回如下所示的结果集:

必需的输出:

StudentID, Month, Year, Present
-------------------------------
1, 1, 2016, P
1, 12, 2016, P
1, 4, 2017, P

这可以通过一个SQL语句实现,而不使用游标。

我正在使用SQL Server 2000数据库。

4 个答案:

答案 0 :(得分:2)

您可以使用计数表生成数字1到12,然后按以下方式交叉应用:

;with cte1 as 
( select * from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) a(n) ) --number generation
,Cte_numbers as ( select num = Row_number() over (order by (SELECT NULL)) from cte1 c1, cte1 c2, cte1 c3)
Select s.StudentId, n.num as [Month], s.[Year], Coalesce(s1.Present,'A') as Present from (
    Select distinct StudentId, [YEAR] from #student ) s
    cross apply ( Select top (12) num from Cte_numbers ) n
left join #student s1
    on s.StudentId = s1.StudentId
    and s.[Year] = s1.[Year]
    and n.num = s1.[Month]
    order by s.StudentId, s.[Year]

答案 1 :(得分:0)

您需要为缺少的实体创建表。例如,具有所有月份的所有月份和年份的月份实体:

CREATE TABLE Month_Table (
    Month_ID int NOT NULL,
    PRIMARY KEY (Month_ID)
);
CREATE TABLE Year_Table (
    Year_ID int NOT NULL,
    PRIMARY KEY (Year_ID)
);

使用1到12之间的数字填充Month_Table,使用2016年至2017年的数字填充Year_Table。

然后使用LEFT OUTER连接用这些表提供的值填充缺失值。如果表中没有包含它们,则使用COALESCE来使用辅助表中的值;如果表中不包含数据,则使用“A”:

SELECT T.StudentID,
   COALESCE(T.Month, Month_Table.Month_ID) Month,
   COALESCE(T.Year, Year_Table.Year_ID) Year,
   COALESCE(T.Present, 'A') Present
FROM YOUR_TABLE T
LEFT OUTER JOIN Month_Table ON Month_Table.Month_ID = YOUR_TABLE
LEFT OUTER JOIN Year_Table ON Year_Table.Year_ID = YOUR_TABLE.Year;

答案 2 :(得分:0)

这里有两个例子,一个使用CTE,递归等,只是为了说明这在SQL Server 2005以上是多么容易,然后是一个应该在SQL Server 2000中运行的例子。

像所有其他答案一样,这基本上是使用数字或计数表来完成繁重的工作。这里有一篇关于如何生成数字的好文章:https://sqlperformance.com/2013/01/t-sql-queries/generate-a-set-1

    double db = 1.2;
    int m = 3;
    System.out.print(String.valueOf(db*m));

答案 3 :(得分:-2)

我认为你可以通过创建一个你需要的所有年月的表(记录)来做到这一点。 样本数据:

CREATE TABLE TD1 (YYEAR SMALLINT, MMONTH SmALLINT);
INSERT INTO TD1 VALUES (2016,1);
INSERT INTO TD1 VALUES (2016,2);
INSERT INTO TD1 VALUES (2016,3);
INSERT INTO TD1 VALUES (2016,4);
INSERT INTO TD1 VALUES (2016,5);
INSERT INTO TD1 VALUES (2016,6);
INSERT INTO TD1 VALUES (2016,7);
INSERT INTO TD1 VALUES (2016,8);
INSERT INTO TD1 VALUES (2016,9);
INSERT INTO TD1 VALUES (2016,10);
INSERT INTO TD1 VALUES (2016,11);
INSERT INTO TD1 VALUES (2016,12);
INSERT INTO TD1 VALUES (2017,1);
INSERT INTO TD1 VALUES (2017,2);
INSERT INTO TD1 VALUES (2017,3);
INSERT INTO TD1 VALUES (2017,4);
INSERT INTO TD1 VALUES (2017,5);
INSERT INTO TD1 VALUES (2017,6);
INSERT INTO TD1 VALUES (2017,7);
INSERT INTO TD1 VALUES (2017,8);
INSERT INTO TD1 VALUES (2017,9);
INSERT INTO TD1 VALUES (2017,10);
INSERT INTO TD1 VALUES (2017,11);
INSERT INTO TD1 VALUES (2017,12);

CREATE TABLE TS1 (StudentId INT, MMONTH SMALLINT, YYEAR SMALLINT, PRESENT CHAR(1))
INSERT INTO TS1 VALUES (1,1,2016,'P');
INSERT INTO TS1 VALUES (1,12,2016,'P');
INSERT INTO TS1 VALUES (1,4,2017,'P');
INSERT INTO TS1 VALUES (2,3,2017,'P');

查询:

SELECT  A.STUDENTID, TD1.MMONTH, TD1.YYEAR, COALESCE(TS1.PRESENT, 'A') AS PRESENT
FROM TD1 
CROSS JOIN (SELECT DISTINCT STUDENTID FROM TS1) A 
LEFT JOIN TS1 On TD1.MMONTH=TS1.MMONTH AND TD1.YYEAR=TS1.YYEAR AND A.STUDENTID = TS1.STUDENTID
ORDER BY A.STUDENTID, TD1.YYEAR, TD1.MMONTH;

输出:

+-----------+--------+-------+---------+
| STUDENTID | MMONTH | YYEAR | PRESENT |
+-----------+--------+-------+---------+
|         1 |      1 |  2016 | P       |
|         1 |      2 |  2016 | A       |
|         1 |      3 |  2016 | A       |
|         1 |      4 |  2016 | A       |
|         1 |      5 |  2016 | A       |
|         1 |      6 |  2016 | A       |
|         1 |      7 |  2016 | A       |
|         1 |      8 |  2016 | A       |
|         1 |      9 |  2016 | A       |
|         1 |     10 |  2016 | A       |
|         1 |     11 |  2016 | A       |
|         1 |     12 |  2016 | P       |
|         1 |      1 |  2017 | A       |
|         1 |      2 |  2017 | A       |
|         1 |      3 |  2017 | A       |
|         1 |      4 |  2017 | P       |
|         1 |      5 |  2017 | A       |
|         1 |      6 |  2017 | A       |
|         1 |      7 |  2017 | A       |
|         1 |      8 |  2017 | A       |
|         1 |      9 |  2017 | A       |
|         1 |     10 |  2017 | A       |
|         1 |     11 |  2017 | A       |
|         1 |     12 |  2017 | A       |
|         2 |      1 |  2016 | A       |
|         2 |      2 |  2016 | A       |
|         2 |      3 |  2016 | A       |
|         2 |      4 |  2016 | A       |
|         2 |      5 |  2016 | A       |
|         2 |      6 |  2016 | A       |
|         2 |      7 |  2016 | A       |
|         2 |      8 |  2016 | A       |
|         2 |      9 |  2016 | A       |
|         2 |     10 |  2016 | A       |
|         2 |     11 |  2016 | A       |
|         2 |     12 |  2016 | A       |
|         2 |      1 |  2017 | A       |
|         2 |      2 |  2017 | A       |
|         2 |      3 |  2017 | P       |
|         2 |      4 |  2017 | A       |
|         2 |      5 |  2017 | A       |
|         2 |      6 |  2017 | A       |
|         2 |      7 |  2017 | A       |
|         2 |      8 |  2017 | A       |
|         2 |      9 |  2017 | A       |
|         2 |     10 |  2017 | A       |
|         2 |     11 |  2017 | A       |
|         2 |     12 |  2017 | A       |
+-----------+--------+-------+---------+