質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

3回答

7741閲覧

特定の値を除く最大値を取得するには?

ms5025

総合スコア292

SQL Server

SQL Serverはマイクロソフトのリレーショナルデータベース管理システムです。データマイニングや多次元解析など、ビジネスインテリジェンスのための機能が備わっています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2018/11/21 04:29

編集2018/11/21 04:42

前提・実現したいこと

エクセルでいうCOUNTIFのMAX版のようなものがSQLにないでしょうか?
:SQLserver

質問

よくあるヘッダと明細のテーブルにて

ヘッダ
伝票番号 0001

明細 日付 金額
明細番号001 2011/11/01 1900
明細番号002 2011/11/02 2900
明細番号003 2011/11/03 3900
明細番号004 2011/11/04 4900
明細番号005 2999/12/31 5900

があるとして、明細データのサマリーを持たせた伝票ヘッダの情報を取得する際、
2999/12/31を覗いた値の中の最大値2011/11/04を「カラムA」として取得したいです。

取得データとしては2999/12/31も含めた金額のサマリーや、2999/12/31も含めた明細数のカウントも必要となります。

この場合一番スマートなSQLはどのようになるでしょうか。

ぱっと思いついたのは
サブクエリで明細の別テーブル(2999/12/31を除いたもの)を用意し、それをJOINしてMAXを取る方法なのですが、エクセルで言うCOUNTIFのMAX版みたいなのがあれば、別テーブルいらないのかなと思いました。

もう少しいい方法はありますか?

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

ベストアンサー

こういうことでしょうか?

sql

1WITH TestTable AS ( 2 SELECT N'伝票番号001'AS [Denpyo], N'明細番号001' AS [Meisai], '2011/11/01' AS [Date], 1900 AS [Price] UNION ALL 3 SELECT N'伝票番号001'AS [Denpyo], N'明細番号002' AS [Meisai], '2011/11/02' AS [Date], 2900 AS [Price] UNION ALL 4 SELECT N'伝票番号001'AS [Denpyo], N'明細番号003' AS [Meisai], '2011/11/03' AS [Date], 3900 AS [Price] UNION ALL 5 SELECT N'伝票番号001'AS [Denpyo], N'明細番号004' AS [Meisai], '2011/11/04' AS [Date], 4900 AS [Price] UNION ALL 6 SELECT N'伝票番号001'AS [Denpyo], N'明細番号005' AS [Meisai], '2999/12/31' AS [Date], 5900 AS [Price] UNION ALL 7 8 SELECT N'伝票番号002'AS [Denpyo], N'明細番号201' AS [Meisai], '2020/11/11' AS [Date], 1900 AS [Price] UNION ALL 9 SELECT N'伝票番号002'AS [Denpyo], N'明細番号202' AS [Meisai], '2020/12/12' AS [Date], 2900 AS [Price] UNION ALL 10 SELECT N'伝票番号002'AS [Denpyo], N'明細番号205' AS [Meisai], '2999/12/31' AS [Date], 5900 AS [Price] 11) 12 13SELECT * 14 15-- MAXの中に CASE 文を書く。 16-- 特定の日付だったらNULLに差し替えてMAXの候補に入らないようにしてしまう 17, MAX( 18 CASE WHEN [Date] = '2999/12/31' THEN NULL 19 ELSE [Date] 20 END 21 ) OVER(PARTITION BY Denpyo) 22 23 AS [MAX内でCASE] 24 25-- サブクエリで取る。 26, ( 27 SELECT MAX([Date]) FROM TestTable sub 28 WHERE [Date] <> '2999/12/31' 29 AND sub.Denpyo = t.Denpyo 30 GROUP BY sub.Denpyo 31 ) 32 AS [サブクエリ] 33 34FROM TestTable t 35ORDER BY t.Denpyo, t.Meisai

とりあえず 2 案。
でもサブクエリの方が個人的にしっくりくるかな…? どうでしょう

投稿2018/11/21 05:05

sk_3122

総合スコア1126

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ms5025

2018/11/21 05:08

ありがとうございます! MAXの中にCASE入れる事できるんですね! サブクエリのほうがsk_3122さん的にはお好みですか?
sk_3122

2018/11/21 05:18

単純に好みの問題でサブクエリの方が好きかな…? というレベルなのですが。 ぱっと見わかりやすい気がする…? という程度です。 あとパフォーマンスとかどうなんでしょうね…? 検証したことは無いのですが。
ms5025

2018/11/21 05:22

ありがとうございます。 やっぱりサブクエリにしておきます。
guest

0

一回で済ませなくてもいいような気もしますが

SQL

1WITH W AS( 2 SELECT * FROM 明細データ WHERE 伝票番号 = '0001' 3) 4SELECT COUNT(T.明細) COUNT, SUM(T.金額) SUM, ( 5 SELECT MAX(T2.日付) FROM W T2 WHERE T2.日付 <> '2999-12-31' 6) カラムA 7FROM W T

投稿2018/11/21 04:54

x_x

総合スコア13749

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ms5025

2018/11/21 04:58

結局サブクエリを使うしかないかなという感じですかね? COUNTみたいに関数内にcase文やIF文書けないのかなーとおもってしまいまして。
ms5025

2018/11/21 05:24

ありがとうございます!MAXにCASE文入れることできるんですね!
guest

0

こんな感じですかね

SQL

1create table tbl(明細 varchar(10),日付 date,金額 int); 2insert into tbl values 3('001','2011/11/01','1900'), 4('002','2011/11/02','2900'), 5('003','2011/11/03','3900'), 6('004','2011/11/04','4900'), 7('005','2999/12/31','5900'); 8select * from tbl as t1 where not exists( 9select 1 from tbl where and 日付<'2999/12/31' and t1.金額<金額 10) and 日付<'2999/12/31'

修正

SQL

1create table tbl(伝票番号 varchar(10),明細 varchar(10),日付 date,金額 int); 2insert into tbl values 3('0001','001','2011/11/01','1900'), 4('0001','002','2011/11/02','2900'), 5('0001','003','2011/11/03','5000'), 6('0001','004','2011/11/04','4900'), 7('0001','005','2999/12/31','5900'), 8('0002','001','2011/11/05','5000');

2999/12/31を除く最大値の日付を持つ金額

SQL

1select 伝票番号,金額 from tbl as t1 where not exists( 2select 1 from tbl where 日付<'2999/12/31' and t1.日付<日付 and t1.伝票番号=伝票番号 3) and 日付<'2999/12/31' and 伝票番号='0001'

投稿2018/11/21 04:46

編集2018/11/21 05:15
yambejp

総合スコア114839

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ms5025

2018/11/21 04:59

詳細は割愛しますがこういった一般的なヘッダ明細の伝票テーブルにおいて T_header(ヘッダ) T_detail(明細) SQL select  T_header.明細番号 ,sum(T_detail.金額) from T_header left join T_detail on T_header.伝票番号=T_detail.伝票番号 結果: 伝票番号0001 , 19500 明細のサマリーを乗せた上記のごくごく一般的な ヘッダと明細のsqlに 上記質問のカラムA(2999/12/31を除く最大日付)を追加でselect対象に入れたい ということでした。
ms5025

2018/11/21 05:00

select  T_header.伝票番号 ,sum(T_detail.金額) from T_header left join T_detail on T_header.伝票番号=T_detail.伝票番号 でしたすいません。
ms5025

2018/11/21 05:24 編集

修正ありがとうございます。 あまりなじみないsqlでちょっと考えてしまったのですが これって結果として 伝票番号0001 , 19500園(明細全ての合計金額), 2011/11/05(2999/12/31をのぞく最大日) という一行がちゃんと返ってくるんでしょうか・・? どこで金額のサマリーが行われてるのかわからなくて・・。 明細の羅列になりません?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問