2016-03-19 12 views
0

私はMySQLの実行計画について十分に理解していないので、可能であればMySQL内のデータのサブセットを操作する方法を理解し、 。異なるレコードを選択すると同時にMySQLからのレコードが最初に出現する

表のユーザー:

+-----------------+-------------+------+-----+---------+----------------+ 
| Field   | Type  | Null | Key | Default | Extra   | 
+-----------------+-------------+------+-----+---------+----------------+ 
| user_id   | int(11)  | NO | PRI | NULL | auto_increment | 
| msisdn   | bigint(20) | NO | UNI | NULL |    | 
| activation_date | datetime | NO |  | NULL |    | 
| msisdn_type  | varchar(32) | NO |  | NULL |    | 
+-----------------+-------------+------+-----+---------+----------------+ 

表のlog_archive:テーブルのユーザーのMSISDNで

+-------------+--------------+------+-----+---------+-------+ 
| Field  | Type   | Null | Key | Default | Extra | 
+-------------+--------------+------+-----+---------+-------+ 
| msisdn  | bigint(11) | NO | MUL | NULL |  | 
| msisdn_type | varchar(32) | NO |  | NULL |  | 
| date  | date   | NO |  | NULL |  | 
| action  | varchar(32) | NO |  | NULL |  | 
+-------------+--------------+------+-----+---------+-------+ 

はユニークですが、log_archiveにはそれがない私は2つのテーブルを持っています。ここで

あなたはこの2つのテーブルのデータをテスト生成されますPHPスクリプトを見つけることができます。

Test data generation script helper

を私は選択する必要があります。

1) All distinct records by msisdn from table log_archive; 
2) By earliest date per msisdn for one specific action only; 
3) For a specific date range from table log_archive; 
4) And to join activation_date from users table with msisdn from both tables. 

は私はあなたに例を挙げましょう。のは、これがlog_archiveテーブルからのサンプルデータであることを言ってみましょう:ここ

+--------------+------------+---------------------+----------------+ 
| msisdn | date | activation_date |  action  | 
|--------------+------------+---------------------+----------------+ 
| 977129764170 | 2016-02-11 | 2014-10-07 00:00:00 | all_services | 
| 977129764170 | 2015-09-05 | 2014-10-07 00:00:00 | app_start  | 
| 977129764170 | 2015-05-08 | 2014-10-07 00:00:00 | widget   | 
| 986629508626 | 2015-07-12 | 2016-02-05 00:00:00 | app_start  | 
| 986629508626 | 2015-03-02 | 2016-02-05 00:00:00 | number_connect | 
| 986629508626 | 2015-05-08 | 2016-02-05 00:00:00 | widget   | 
| 986629508626 | 2015-01-08 | 2016-02-05 00:00:00 | app_start  | 
| 933563888440 | 2016-02-20 | 2014-10-06 00:00:00 | all_services | 
| 933563888440 | 2015-03-12 | 2014-10-06 00:00:00 | app_start  | 
| 933563888440 | 2015-04-26 | 2014-10-06 00:00:00 | number_connect | 
| 933563888440 | 2015-10-17 | 2014-10-06 00:00:00 | all_services | 
| 943730853721 | 2015-06-19 | 2015-05-01 00:00:00 | widget   | 
| 943730853721 | 2015-12-08 | 2015-05-01 00:00:00 | app_start  | 
| 943730853721 | 2016-02-09 | 2015-05-01 00:00:00 | app_start  | 
+--------------+------------+---------------------+----------------+ 

ので明確なのMSISDNは977129764170、986629508626、933563888440、943730853721です。アクション欄には「app_start」を等しい個別のMSISDN値の

最も早い日付は次のとおりです。

977129764170 is 2015-09-05 
986629508626 is 2015-01-08 
933563888440 is 2015-03-12 
943730853721 is 2015-06-19 

私は私にこの出力を与えるようにSQLを作成する必要があります。

+--------------+------------+---------------------+----------------+ 
| msisdn | date | activation_date |  action  | 
|--------------+------------+---------------------+----------------+ 
| 977129764170 | 2015-09-05 | 2014-10-07 00:00:00 | app_start  | 
| 986629508626 | 2015-01-08 | 2016-02-05 00:00:00 | app_start  | 
| 933563888440 | 2015-03-12 | 2014-10-06 00:00:00 | app_start  | 
| 943730853721 | 2015-12-08 | 2015-05-01 00:00:00 | app_start  | 
+--------------+------------+---------------------+----------------+ 

だから私がする必要がありますapp_startアクションが発生する最も古い日付のすべての個別のmsisdnsを選択し、その個別のmsisdによってユーザーテーブルからactivation_dateに参加します。日付欄から特定の日付範囲のみを検索することもできます。

ノー結果と、このSQLでそれを試してみました:

SELECT DISTINCT(log_archive.msisdn) as msisdn, DATE(log_archive.date) AS actionDate, users.activation_date 

FROM log_archive 

INNER JOIN users on log_archive.msisdn = users.msisdn 

WHERE log_archive.action = 'app_start' && log_archive.date BETWEEN '2015-01-08' AND '2016-03-15' 

ORDER BY actionDate ASC; 

私はDISTINCT使用していても何度も同じMSISDN多くを得ます。

サブクエリを使用する必要がありますか?

+0

DISTINCT削除して、GROUP BYを使用するには、私はそれを行うことはできません –

+0

@BerndBuffenをlog_archive.msisdn。希望する出力を説明する部分をお読みください。 –

答えて

1

あなたはGROUP BYは、各MSISDNについてMIN(date)を取得したいと思います。私たちは行動によってそれ以来、グループ化されていない各フィールドを集約しなければならないので、我々はまた、MIN(action)を追加

SELECT msisdn, MIN(date) date, MIN(action) action 
FROM log_archive 
WHERE action='app_start' 
    AND date BETWEEN '2015-01-08' AND '2016-03-15' 
GROUP BY msisdn 

はうまく機能MIN、選択したすべての行についても同様です。

これを取得したら、結合を追加するのは簡単です。私はlog_archive.action =「app_start」の発生最古のレコードを取得することはできませんので

SELECT a.msisdn, MIN(a.date) date, u.activation_date, MIN(a.action) action 
FROM log_archive a 
JOIN users u 
    ON u.msisdn = a.msisdn 
WHERE a.action='app_start' 
    AND a.date BETWEEN '2015-01-08' AND '2016-03-15' 
GROUP BY a.msisdn 
+0

私はあなたのSQLをテストしているので、すべてがうまくいきます。なぜ私はグループ化されていない各フィールドを集計する必要があるのか​​理解できません。ありがとうalot men :) –

+1

@CaslavSabaniこれは標準SQLの必要条件ですが、MySQLはデフォルトではそれがなくても離れることができます(グループ内の疑似ランダム行の値を表示します)。この場合、行は同じ 'action'値を持つので、正しい結果が得られますが、他のデータベースシステムを使いたい場合には、習得するのが良い習慣です。 –

+0

返事をありがとう。 GROUP BYと集計関数との関係について、MySQLとSQLの一般的な内容を読むことができるいくつかの参考文献を教えてください。または、Googleでどのように検索できますか?どこで私はMySQLの実行計画について知ることができますか? –

0

SDISTINCTはすべての返された列を調べるため、返されるデータの行は異なります。したがって、log_archiveの個別の行のみを結合したい場合は、結合前にサブクエリでそれを使用します。 ように:

(SELECT DISTINCT * FROM log_archive) AS distinct_Log INNER JOIN... 
関連する問題