SQL 面接の質問: 時間差の合計を求める (重複は無視)

SQL 面接の質問: 時間差の合計を求める (重複は無視)

ある会社の BI 職の面接を受けたとき、面接で SQL に関する質問がありました。一見すると非常に簡単に思えましたが、書いてみると要約が足りず、すぐに書き出すことができませんでした。

トピックは次のとおりです。

各ブランドのプロモーション日数を調べる

テーブル sale はプロモーション マーケティング テーブルです。データには重複した日付があります。たとえば、id 1 の end_date は 20180905 で、id 2 の start_date は 20180903 です。つまり、id 1 と id 2 には重複した販売日があります。各ブランドのプロモーション日数を調べます (重複はカウントされません)

表の結果は次のとおりです。

+------+-------+------------+------------+
| ID | ブランド | 開始日 | 終了日 |
+------+-------+------------+------------+
| 1 | ナイキ | 2018-09-01 | 2018-09-05 |
| 2 | ナイキ | 2018-09-03 | 2018-09-06 |
| 3 | ナイキ | 2018-09-09 | 2018-09-15 |
| 4 | oppo | 2018-08-04 | 2018-08-05 |
| 5 | oppo | 2018-08-04 | 2018-08-15 |
| 6 | 生体内 | 2018-08-15 | 2018-08-21 |
| 7 | 生体内 | 2018-09-02 | 2018-09-12 |
+------+-------+------------+------------+

最終結果は

ブランド全ての日
ナイキ13
オッポ12
生体内18

テーブルステートメントの作成

-- ----------------------------
-- テーブル構造を販売中
-- ----------------------------
`sale` が存在する場合はテーブルを削除します。
テーブル「sale」を作成します(
 `id` int(11) デフォルト NULL,
 `brand` varchar(255) デフォルト NULL,
 `start_date` 日付 デフォルト NULL、
 `end_date` 日付 デフォルト NULL
)ENGINE=InnoDB デフォルト文字セット=utf8;

-- ----------------------------
-- 販売記録
-- ----------------------------
`sale` に VALUES (1, 'nike', '2018-09-01', '2018-09-05') を挿入します。
`sale` に VALUES (2, 'nike', '2018-09-03', '2018-09-06') を挿入します。
`sale` に VALUES (3, 'nike', '2018-09-09', '2018-09-15') を挿入します。
`sale` に VALUES (4, 'oppo', '2018-08-04', '2018-08-05') を挿入します。
`sale` に VALUES (5, 'oppo', '2018-08-04', '2018-08-15') を挿入します。
`sale` に VALUES (6, 'vivo', '2018-08-15', '2018-08-21') を挿入します。
`sale` に値 (7、'vivo'、'2018-09-02'、'2018-09-12') を挿入します。

方法1:

次のレコードへの自己関連付けの方法を使用する

ブランドを選択、合計(終了日-開始日+1)、全日数から 
 (
 s.idを選択し、
  s.ブランド、
  s.開始日、
  s.end_date 、 
  if(s.start_date>=ifnull(t.end_date,s.start_date) ,s.start_date,DATE_ADD(t.end_date,interval 1 day) ) を before_date として
 sale s の左から join (select id+1 as id ,brand,end_date from sale) t on s.id = t.id and s.brand = t.brand
 s.idで並べ替え
 )tmp
 ブランド別にグループ化

運用結果

+-------+---------+
| ブランド | all_day |
+-------+---------+
| ナイキ | 13 |
| 反対 | 12 |
| 生体 | 18 |
+-------+---------+

この方法はこの質問の表には有効ですが、不連続な ID を持つブランドのレコードには適用できない可能性があります。

方法2:

SELECT a.brand,SUM(
 場合 
  a.start_date=b.start_date かつ a.end_date=b.end_date の場合
  存在しない(
  選択*
  sale c から LEFT JOIN sale d ON c.brand=d.brand 
   ここで、d.brand = a.brand
   かつ、c.start_date=a.start_date
   かつ c.id<>d.id 
   AND (d.start_date が c.start_date と c.end_date の間であり、d.end_date>c.end_date
   または 
  c.start_date が d.start_date と d.end_date の間であり、c.end_date>d.end_date である)
    ) 
   その後 (a.終了日 - a.開始日 + 1) 
  (a.id<>b.id かつ b.start_date が a.start_date かつ a.end_date かつ b.end_date>a.end_date の間) の場合、(b.end_date-a.start_date+1)
  そうでなければ0終了
  ) 毎日 
sale a から sale b を JOIN し、 a.brand=b.brand を GROUP BY a.brand にします。

運用結果

+-------+----------+
| ブランド | all_days |
+-------+----------+
| ナイキ | 13 |
| 反対 | 12 |
| 生体 | 18 |
+-------+----------+

条件の中には

d.start_date が c.start_date と c.end_date の間であり、かつ d.end_date>c.end_date である
   または 
c.start_date が d.start_date と d.end_date の間であり、c.end_date が d.end_date より大きい

置き換え可能

c.開始日 < d.終了日 かつ (c.終了日 > d.開始日)

結果も正しい

分析関数を使うことも可能です。私のパソコンにはまだOracleがインストールされていないので、MySQLで書きました。

以上がこの記事の全内容です。皆様の勉強のお役に立てれば幸いです。また、123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • PHPとMySqlで時間差を計算する方法の詳細な説明
  • mysql 時間差計算関数
  • PHP と MySql で時間差を計算する方法

<<:  Linux のユーザーとグループ管理によく使われるコマンドの概要

>>:  vue+canvasでタイムラインを描く方法

推薦する

高品質なJavaScriptコードの書き方

目次1. 読みやすいコード1. 統一コード形式2. マジックナンバーを削除する3. 単一機能原則2....

MySQLの行数カウントに関する簡単な説明

各テーブルの行数をカウントするために使用される MySQL count() 関数は、誰もがよく知って...

CSS ブラウザ互換性の問題に対する 4 つの解決策

フロントエンドは、技術が急速に進化するだけでなく、知っておくべき事柄が多すぎるという理由で大変な仕事...

JavaScript における URL オブジェクトの素晴らしい使い方

目次序文解析パラメータURLパラメータを変更する要約する序文URLオブジェクトはページ側ではあまり使...

Ubuntuにopencvをインストールする正しい方法の詳細な説明

この記事ではUbuntuでC++インターフェースを使用してopencvをインストールする方法について...

Javascript 文字列メソッドの詳細な説明

目次文字列の長さ: 長さcharAt() charCodeAt()文字列に値が含まれているかどうかを...

Vueコンポーネント通信方法事例まとめ

目次1. 親コンポーネントが子コンポーネントに値を渡す(props) 2. サブコンポーネントは親コ...

Mysql の 2 つのテーブル間の結合クエリの 4 つの状況の概要

一般的に言えば、より完全な結果を得るためには、2 つ以上のテーブルから結果を取得する必要があります。...

jQueryはネストされたタブ機能を実装します

この記事では、ネストされたタブ機能を実装するためのjQueryの具体的なコードを参考までに紹介します...

DockerのTLS(SSL)証明書の有効期限の問題を解決する

問題現象: [root@localhost ~]# docker イメージをプル xxx.com.c...

Vue でインデックスをキー属性値として使用することが推奨されないのはなぜですか?

目次序文キーの役割差分アルゴリズムにおけるキーの役割ヘッドノードを同期するテールノードを同期する新し...

Dockerコンテナとローカルマシン間でファイルを転送する方法

ホストとコンテナ間でファイルを転送するには、コンテナの完全な ID が必要です。取得方法は以下の通り...

MySql 8.0 と対応するドライバー パッケージの一致に関する注意事項

MySql 8.0 対応ドライバパッケージのマッチングMySql データベースをバージョン 8.0 ...

Nginx はリクエスト接続を統合し、ウェブサイトのアクセス例を高速化します

序文世界最高の Web サーバーの 1 つである Nginx の利点は明らかです。 Nginx がリ...

MySQL 論理バックアップとリカバリ テストの概要

目次1. データベース論理バックアップとはどのようなバックアップですか? 2. よく使われる論理バッ...