4

我有一个电影数据库,我想列出那一年我没有电影的年份。所以我需要的只是一个列表(1900 .. 2012),然后我可以加入和加入,而不是加入我想要的所有内容。

我有:

CREATE PROCEDURE build_years(p1 SMALLINT) 
BEGIN 
    CREATE TEMPORARY TABLE year (year SMALLINT(5) UNSIGNED); 
    label1: LOOP 
        INSERT INTO year VALUES (p1); 
        SET p1 = p1 + 1; 
        IF p1 > 2012 THEN LEAVE label1; END IF; 
    END LOOP; 
END 

但这似乎太不符合 SQL 了,而且只比运行 Python 代码创建同一个表稍微少一些。我真的很喜欢不使用存储过程、不使用循环并且不使用实际表的东西,按照关注的顺序。

4

6 回答 6

4

这应该可以工作,直到您需要超过 195 年,此时您需要添加UNION ALL

SELECT Year 
FROM   (   SELECT @i:= @i + 1 AS YEAR
           FROM   INFORMATION_SCHEMA.COLLATION_CHARACTER_SET_APPLICABILITY,
                  ( SELECT @i:= 1899) AS i
        ) As Y
WHERE   Year BETWEEN 1900 AND 2012
ORDER BY Year;

尽管我假设COLLATION_CHARACTER_SET_APPLICABILITYSystem 表的默认大小为 195,但基于我可信赖的测试场SQL Fiddle

于 2012-06-06T22:10:46.460 回答
3

几年前我也遇到过类似的问题。我的解决方案是:

1.序列表

我创建了一个表格,其中填充了从 0 到 < 所需数量 > 的整数序列:

CREATE TABLE numbers (n INT);
INSERT INTO numbers VALUES (0),(1),(2),(3),(4);
INSERT INTO numbers SELECT n+5 FROM numbers;
INSERT INTO numbers SELECT n+10 FROM numbers;
INSERT INTO numbers SELECT n+20 FROM numbers;
INSERT INTO numbers SELECT n+40 FROM numbers;
etc.

它只执行一次,因此可以从您的应用程序外部创建,甚至可以手动创建。

2.选择所需类型和范围的数据

对于整数很明显 - 即范围 1..99:

SELECT n FROM numbers WHERE n BETWEEN 1 AND 99;

日期 - 从现在到 +2 天的 2 小时间隔:

SELECT date_add(now(),INTERVAL 2*n HOUR) FROM numbers WHERE n BETWEEN 0 AND 23;

所以在你的情况下,它可能是:

SELECT n+1900 AS n_year FROM numbers WHERE n BETWEEN 0 AND 112;

然后JOIN就可以了n_year

于 2012-06-06T21:22:11.153 回答
1

如果您真的想将其保留在查询中,这将返回 2012 到 1900 的列表。

SELECT 
    TO_CHAR (ADD_MONTHS (TRUNC (SYSDATE, 'YYYY'), ((rno - 1) * -12)), 'YYYY') AS "years"
FROM 
    (
    SELECT 
        LEVEL rno
    FROM DUAL
    CONNECT BY LEVEL <=
                   (SELECT TO_CHAR (TRUNC (SYSDATE, 'YYYY'), 'YYYY')
                           - 1899
                               yearstobuild
                      FROM DUAL))
于 2012-06-06T21:23:10.190 回答
0

根据您的意愿,我能想到的唯一解决方案也很糟糕...

SELECT years.year FROM
    (
        SELECT 1900 AS year
        UNION SELECT 1901
        ...
        UNION SELECT 2012
    ) AS years
    LEFT OUTER JOIN yourmovietable USING (year)
WHERE yourmovietable.year IS NULL;
于 2012-06-06T21:21:12.297 回答
0

使用这个通用查询更快:

INSERT INTO numbers SELECT n+(SELECT COUNT(*) FROM numbers) FROM numbers;    

每个查询执行重复:

INSERT INTO numbers VALUES (0),(1),(2),(3),(4);

INSERT INTO numbers SELECT n+(SELECT COUNT(*) FROM numbers) FROM numbers;
INSERT INTO numbers SELECT n+(SELECT COUNT(*) FROM numbers) FROM numbers;
INSERT INTO numbers SELECT n+(SELECT COUNT(*) FROM numbers) FROM numbers;

...

于 2017-11-20T13:08:10.667 回答
-1
select year into temporary table blaa from (generate_series(1900,2000)) where year not in(select distinct(year) from films)

不知道这是否可行,但你会得到漂移。

于 2012-06-06T20:52:32.127 回答