直近2年度連続で減少していない年度を抽出する方法

このQ&Aのポイント
  • 直近2年度連続で減少していない年度を抽出する方法を説明します。
  • テーブルの時系列から抜けている部分を考慮しながら、直近2年度連続で減少していない年度を抽出する方法について解説します。
  • 上記のテーブルを使用して、直近の年度までのデータを表示する方法は分かるが、2年連続での判定方法が分からない。
回答を見る
  • ベストアンサー

直近2年度連続で減少していない年度を抽出

以下のテーブルの様に時系列が抜けているテーブルから直近2年度連続で減少していない年度を 抽出しようとしています。 /* year|sale --------- 1990|50 1992|50 1993|52 1994|55 1997|55 */ /* CREATE TABLE sales2 (year INTEGER NOT NULL , sale INTEGER NOT NULL , PRIMARY KEY (year)); INSERT INTO sales2 VALUES (1990, 50); INSERT INTO sales2 VALUES (1992, 50); INSERT INTO sales2 VALUES (1993, 52); INSERT INTO sales2 VALUES (1994, 55); INSERT INTO sales2 VALUES (1997, 55); */ 以下の記述で直近の年度までなら表示できているとは思うのですが2年連続となると やり方が思いつきません。誰かご教授いただけないでしょうか? select year,sale from sales2 s1 where sale >=(select sale from sales2 s2 where s2.year = (select max(year) from sales2 s3 where s1.year > s3.year)) order by year ;

質問者が選んだベストアンサー

  • ベストアンサー
  • Siegrune
  • ベストアンサー率35% (316/895)
回答No.1

>時系列が抜けている 抜けている年度の値はどうするのでしょう? 例: 1993 56 1994 55 1995 ?(抜け) 1996 ?(抜け) 1997 53 1997は2年連続減少? 2年連続減少とは限りませんが。 (抜けが0だと考えると、2年連続減少ではない。データのある年度でいうと2年連続減少である。) というのを気にしないで、単にあるレコードのみで判定するのなら、 前々のレコードを調べたいなら、 (select max(year) from sales2 s3 where s1.year > s3.year)) で求めたmax(year)より小さいmax(year)を求めれば出てくるわけですから、 select year,sale from sales2 s1 where sale >=(select sale from sales2 s2 where s2.year = (select max(year) from sales2 s3 where s1.year > s3.year)) or sale >=(select sale from sales2 s2 where s2.year = (select max(year) from sales2 s3 where (select max(year) from sales2 s4 where s1.year > s4.year) > s3.year) ) order by year ; で求まります。 (未検証ですが。)

yoshi2519
質問者

お礼

ご回答ありがとうございます! なるほど。こういう記述になるんですね。 理解するのに時間がかかってしまいましたが 望み通りの抽出ができました。

その他の回答 (1)

  • mitoneko
  • ベストアンサー率58% (469/798)
回答No.2

 以前、連続2年上昇を考えたことがありますよね。  連続2年減少なら、簡単です。前回のSQLの不等号をひっくり返すだけ。  本当に問題の表現が正確であるのならば、 select sm.year, sm.sale from sales sm where not exists(     select sc.year, sc.sale     from sales sc join sales s1 on s1.year = sc.year -1             join sales s2 on s2.year = sc.year - 2     where s1.sale < s2.sale and sc.sale < s1.sale and sm.year=sc.year)  で、いけるともおいます。  サブクエリの中でやっていることは、2年連続で減少しているレコードの一覧の抽出です。前回のSQLと同じ方法ですね。  これをnot existsで否定しています。  さて、恒例の問題への条件です。  今回は、「減少していない」という表現だったので、前年度・前々年度が存在しない場合も含みます。実は、そのために、SQLが少々複雑な表現になっています。こうしないと、NULLの扱いが面倒なんです。存在しない年度との比較結果は、「減少していません」としています。増加もしていないし、同値でも無いんですけどね。  yearがきちんと一意であるか一意化できることが前提になるのは、前回の2年連続増加と同じです。

yoshi2519
質問者

お礼

ご回答ありがとうございます。 色んな記述方法があるんですね~。 まだSQLを学び始めたばかりなので サブクエリには苦戦しっぱなしです。

関連するQ&A

  • SQLで2年連続で値が上昇した年を表示する

    添付の表よりSQLのcase文を使用して2年連続でsaleが上がったyearを求めようと しています。 前年より上がった場合は以下のSQLで表示できたのですが 2年連続に上がった年を表示させようとするとうまく表示できません。 誰かご教授いただけないでしょうか? select year,sale from sales s1 where sale > (select sale from sales s2 where s2.year = s1.year -1) order by year

  • SQLの抽出について

    現在、SQLの課題にとりくでいるのですが、paizaで ERROR 1054 (42S22) at line 9: Unknown column 'BMI' in 'where clause' この様なエラー表示が出てしまい、修正方法を教えて頂けないでしょうか? 「課題」 BMIの値が25以上の社員のみ抽出するよう変更せよ。  ただしBMIを算出する計算式は一箇所のみ(複数箇所に記載しないもの)とする。 「ソースコード」 create table employees(employeename varchar(100), height integer, weight integer); INSERT INTO employees(employeename, height, weight) VALUES ('後藤', 170, 50); INSERT INTO employees(employeename, height, weight) VALUES ('齋藤', 180, 90); INSERT INTO employees(employeename, height, weight) VALUES ('佐藤', 170, 80); select *, 10000 * weight / (height * height) AS BMI from employees WHERE BMI>=25;

  • TO_NUMBERの結果は、カラムに追加できない?

    いつもお世話になっています。 TO_NUMBER実行時、結果はnumeric型で取得できると思うのですが、 その値をカラムに追加することはできるのでしょうか? insert into number2 values((select numberStr,TO_NUMBER (numberStr,'000.000') from number),'aaa'); 実行すると、 副問い合わせは1列のみを返さなければなりませんというErrorが生じます。 なのでwhere句を追加しましたが、結果は同じです。 実行したsqlは、 create table number ( count integer not null primary key, numberStr varchar(20) not null ); create table number2 ( no numeric not null primary key, numberS varchar(30) not null); insert into number values(5,'555.55000'); insert into number2 values((select numberStr,TO_NUMBER (numberStr,'000.000') from number where count=5),'aaa'); です。 宜しくお願いします。

  • SQLの数値への単位について

    現在SQLをpaizaにて実行してるのですが ・highにcm wightにkgの単位の付け方 ・UPDATE DELETEが上手く実行されない の二点の修正方法が分からず、どなたか教えて頂けないでしょうか? 「ソースコード」 create table employees(height integer, weight integer); INSERT INTO employees(height, weight) VALUES(170, 50); INSERT INTO employees(height, weight) VALUES(180, 90); INSERT INTO employees(height, weight) VALUES(165, 70); SELECT height FROM employees; SELECT height AS tall FROM employees; UPDATE employees SET height ='171' WHERE weight ='170'; DELETE FROM employees WHERE height ='180'; 「実行結果」 height 170 180 165 tall 170 180 165

    • ベストアンサー
    • MySQL
  • 測定結果が決められた範囲内か判定するSQL文

    決められた範囲内に測定結果が入っているかを判定するSQL文(またはストアドプロシージャ)を PostgreSQL 14.0を使って作ろうとしていますが、正しい結果が得られません。 具体的には、ケーブル・テーブルとスペック・テーブルで一致するテスト項目同士(例えば、'Test_1'同士)だけを比較したいのですが、他のテスト項目も引っ掛けてしまいます。 あと、下記のwhere test_item = 'Test_1', 'Test_2', 'Test_3'の部分を select test_item from cable; から一つ一つ取り出してループで回して代入し、最終的には id | test_item | test ----+-----------+------ 1 | Test_1 | 1.5 2 | Test_1 | 1.8 2 | Test_2 | 2.5 という、まとまった出力を得たいのですが、その方法を教えていただけないでしょうか? 自作のテーブルとSQL文は以下になります: create table cable( id integer default 0 not null ,test_item varchar(30) not null ,test numeric(3, 1) ,primary key (id, test_item) ); insert into cable values(1, 'Test_1', 1.5); insert into cable values(1, 'Test_2', 4.5); insert into cable values(1, 'Test_3', 2.5); insert into cable values(2, 'Test_1', 1.8); insert into cable values(2, 'Test_2', 2.5); insert into cable values(3, 'Test_3', 2.5); create table spec( test_item varchar(30) not null , lower_spec numeric(3, 1) , upper_spec numeric(3, 1) , primary key(test_item) ); insert into spec values('Test_1', 1.0, 2.0); insert into spec values('Test_2', 2.0, 3.0); insert into spec values('Test_3', 3.0, 4.0); postgres=# select * from cable c WHERE c.test_item = test_item and test < (select upper_spec from spec where test_item = 'Test_1') and test > (select lower_spec from spec where test_item = 'Test_1'); id | test_item | test ----+-----------+------ 1 | Test_1 | 1.5 2 | Test_1 | 1.8 (2 行) postgres=# select * from cable c WHERE c.test_item = test_item and test < (select upper_spec from spec where test_item = 'Test_2') and test > (select lower_spec from spec where test_item = 'Test_2'); id | test_item | test ----+-----------+------ 1 | Test_3 | 2.5 ←'Test_3'なので引っ掛けたくない 2 | Test_2 | 2.5 3 | Test_3 | 2.5 ←'Test_3'なので引っ掛けたくない (3 行) postgres=# select * from cable c WHERE c.test_item = test_item and test < (select upper_spec from spec where test_item = 'Test_3') and test > (select lower_spec from spec where test_item = 'Test_3'); id | test_item | test ----+-----------+------ (0 行) 必要であれば補足します。 では、よろしくお願いします。

  • 配列データに対する、要素の追加・削除方法

    PostgreSQLの配列に対して、要素の追加及び削除を行いたいのですが、下記のような動作をさせるには、※1と※2で、どのようなSQLを実行すれば良いでしょうか? よろしくお願いいたします。 >>> CREATE TABLE test ( id integer, data integer[] ); INSERT INTO test VALUES (1, '{0,1,2,3,4}'); INSERT INTO test VALUES (2, '{5,6,7,8,9}'); SELECT * FROM test; id | data ----+------------- 1 | {0,1,2,3,4} 2 | {5,6,7,8,9} (2 rows) UPDATE test [data配列に10を追加] WHERE id = 1; /* ※1 */ UPDATE test [data配列から6を除去] WHERE id = 2; /* ※2 */ SELECT * FROM test; id | data ----+------------- 1 | {0,1,2,3,4,10} 2 | {5,7,8,9} (2 rows) <<<

  • SQLiteのLike句で抽出できない

    SQLiteのLike句で抽出できないレコードがあります。 原因についてご教授いただけますでしょうか。 以下、操作手順になります。 ■データベースの作成 C:\>sqlite3.exe member.db SQLite version 3.7.15.2 2013-01-09 11:53:05 Enter ".help" for instructions Enter SQL statements terminated with a ";" ■テーブルの作成、レコードの追加 sqlite> create table t_member(name text, age integer); sqlite> insert into t_member values('山田一郎', 25); sqlite> insert into t_member values('田中次郎', 35); sqlite> insert into t_member values('鈴木三郎', 45); ■検索 sqlite> select * from t_member where name like '%一郎'; 山田一郎|25 sqlite> select * from t_member where name like '%次郎'; 田中次郎|35 sqlite> select * from t_member where name like '%三郎'; sqlite> 三郎だけが検索条件に適合しないのは何故でしょうか。 よろしくお願いします。

  • tutorial/funcs.sqlの中のSQL文

    の中に CREATE TABLE EMP ( name text, salary integer, age integer, cubicle point ); INSERT INTO EMP VALUES ('Sam', 1200, 16, '(1,1)'); INSERT INTO EMP VALUES ('Claire', 5000, 32, '(1,2)'); INSERT INTO EMP VALUES ('Andy', -1000, 2, '(1,3)'); INSERT INTO EMP VALUES ('Bill', 4200, 36, '(2,1)'); INSERT INTO EMP VALUES ('Ginger', 4800, 30, '(2,4)'); -- the argument of a function can also be a tuple. For instance, -- double_salary takes a tuple of the EMP table CREATE FUNCTION double_salary(EMP) RETURNS integer AS 'SELECT $1.salary * 2 AS salary' LANGUAGE SQL; SELECT name, double_salary(EMP) AS dream FROM EMP WHERE EMP.cubicle ~= '(2,1)'::point; というコードが有るのですが 最後のWHERE EMP.cubicle ~= '(2,1)'::pointの ~= はどういうもので どんなときにつかうのでしょうか? また単なる = ではエラーになるようなのですが=との使い分けはどのようにすれば良いのでしょうか? よろしくお願いします

  • 同時アクセス

    例えば bigCategory,midleCategoryテーブルがあり、(今回はmiddleCategoryがbigCategoryときーでつながっている) create table bigCategory ( num integer not null primary key, name varchar(20) not null, ); insert into bigCategory values(0,'category_1'); insert into bigCategory valuers(1,'category_2'); create table middleCategory ( num integer not null primary key, name varchar(20) not null, bigkey integer not null ); insert into middleCategory values(0,'middle_1',0); insert into middleCategory values(1,'middle_2',1); bigCategoryの変更・削除をするときに、 1)middleCategoryがselectされている → 変更不可 2)middleCategoryがselectされていない →変更・削除可能 3)また、middleCategoryはselectされてなくて、 bigCategoryテーブルの変更行が他からselectされていたら、変更・削除不可 といった状況を実現したいのですが、可能なのでしょうか? 候補として、おもうはGRANTかな、と思ったりはするのですが。 いろいろ考えはするのですが、解決策が思いつかず質問させてもらいました。 宜しくお願いします。

  • 指定された趣味を持つメンバーがいるグループを抽出するSQL

    グループテーブル、メンバーテーブル、趣味テーブルの3つのテーブルがあります。 あるメンバーはあるグループに属しており、趣味を1つ持っています。 以下がそのSQLです。 CREATE TABLE groups ( g_id int primary key ); CREATE TABLE members ( m_id int primary key , g_id int , h_id int ); CREATE TABLE hobbies ( h_id int primary key, h_name text ); INSERT INTO groups VALUES ( 1 ); INSERT INTO groups VALUES ( 2 ); INSERT INTO groups VALUES ( 3 ); INSERT INTO members VALUES ( 1, 1, 1); INSERT INTO members VALUES ( 2, 1, 3); INSERT INTO members VALUES ( 3, 1, 4); INSERT INTO members VALUES ( 4, 1, 4); INSERT INTO members VALUES ( 5, 2, 1); INSERT INTO members VALUES ( 6, 2, 2); INSERT INTO members VALUES ( 7, 2, 3); INSERT INTO members VALUES ( 8, 3, 2); INSERT INTO members VALUES ( 9, 3, 3); INSERT INTO members VALUES ( 10, 3, 4); INSERT INTO hobbies VALUES ( 1, 'sports' ); INSERT INTO hobbies VALUES ( 2, 'music' ); INSERT INTO hobbies VALUES ( 3, 'book' ); INSERT INTO hobbies VALUES ( 4, 'drive' ); 指定された趣味を持つメンバーがいるグループを抽出するにはどうすればいいでしょうか? 例えば、「読書が趣味なメンバーとドライブが趣味なメンバーがいるグループは?」「グループ1とグループ3」のような感じです。 一応自分で考えてみたのが、以下ですが、これだと趣味の指定が増減すると大きくSQLが変わってしまいます。 もっといいやり方はないでしょうか? 私はPostgreSQL8を使ってますが、汎用的なSQLであれば、そっちの方がいいです。 SELECT distinct m.g_id FROM members m join hobbies h ON m.h_id = h.h_id where h.h_name = 'drive' INTERSECT SELECT distinct m.g_id FROM members m join hobbies h ON m.h_id = h.h_id where h.h_name = 'book';