5

user(id、name、join_on)というmysqlテーブルがあります。joinonは、毎日何回の使用が作成されたかを表示する日付フィールドです。groupbyを使用できますが、ユーザーが取得した日付のみが表示されます。日付のように追加

4/12/10  5 users added
4/13/10  2 users added
4/15/10  7 users added

ここでは、2010年4月14日の日付が欠落しているため、1か月のすべての日付をリストしたいと思います。日付を追加するためだけに別のテーブルを作成することで解決策が1つあり、そのテーブルはjoin_onでusersテーブルに結合されたままになり、合計結果が得られますが、作成に関しては、エントリを作成して追加する必要があります。日付表で、そうするための別のアプローチを提案してください。

ありがとうございました。

4

3 に答える 3

4

GROUP BYを使用してから、実際のコードで欠落している日付を追加する方が簡単な場合があります(または、日付範囲全体を繰り返し処理し、クエリ結果から日付が欠落している場合はゼロを出力します)。

すべてをSQLで解決する必要はなく、他の場所で解決する方が簡単なこともたくさんあります。:)

于 2010-04-16T07:20:47.130 に答える
2

純粋なSQLでこれを実行できるアプローチがありますが、制限があります。

最初に、行として数列1、2、3 ... nを設定する必要があります(それをselect row from rows返すと仮定します)。

次に、これに参加したままにして、最小から最大までの日数に基づいて日付に変換できます。

 select @min_join_on := (select min(join_on) from user);
 select @no_rows := (select datediff(max(join_on), @min_join_on) from user)+1;

必要な行数が表示され、これを使用して次のことができます。

 select adddate(@min_join_on, interval row day) from rows where row <= @no_rows;

必要な日付のシーケンスが返されます。その後、左結合を実行してユーザーテーブルに戻すことができます。
サブクエリを使用すると、変数の使用を回避できます。読みやすくするために分解しました。

ここで問題となるのは、テーブルの行数がrows@no_rowsよりも大きくなければならないことです。10,000行の場合、最大27年の日付範囲で作業でき、100,000行の場合、最大273年の日付範囲で作業できます(これは非常に気分が悪いですが、ストアドプロシージャを使用したくない場合は、恐れ入ります。見た目も違和感もあります)。

したがって、このような固定の日付範囲で作業できる場合は、テーブルを次のようなクエリに置き換えることもできます。

SELECT @row := @row + 1 as row FROM (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t, (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t2, (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t3, (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t4, (SELECT @row:=0) r

これにより、1から10,000までの10,000行が生成され、ひどく非効率になることはありません。

したがって、最終的には1つのクエリで実行できます。

create table user(id INT NOT NULL AUTO_INCREMENT, name varchar(100), join_on date, PRIMARY KEY(id));

mysql> select * from user;
+----+-------+------------+
| id | name  | join_on    |
+----+-------+------------+
|  1 | user1 | 2010-04-02 | 
|  2 | user2 | 2010-04-04 | 
|  3 | user3 | 2010-04-08 | 
|  4 | user4 | 2010-04-08 | 
+----+-------+------------+
4 rows in set (0.00 sec)

insert into user values (null, 'user1', '2010-04-02'), (null, 'user2', '2010-04-04'), (null, 'user3', '2010-04-08'), (null, 'user4', '2010-04-08')


SELECT date, count(id)
FROM (
SELECT adddate((select min(join_on) from user), row-1) as date 
FROM ( 
SELECT @row := @row + 1 as row FROM (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t, (select 0 union all select 1 union all select 3 union all select 4 union all select 5 union all select 6 union all select 6 union all select 7 union all select 8 union all select 9) t2, (SELECT @row:=0) r ) n  
WHERE n.row <= ( select datediff(max(join_on), min(join_on)) from user) + 1
) dr LEFT JOIN user u ON dr.date = u.join_on
GROUP BY dr.date

+------------+-----------+
| date       | count(id) |
+------------+-----------+
| 2010-04-02 |         1 | 
| 2010-04-03 |         0 | 
| 2010-04-04 |         1 | 
| 2010-04-05 |         0 | 
| 2010-04-06 |         0 | 
| 2010-04-07 |         0 | 
| 2010-04-08 |         2 | 
+------------+-----------+
7 rows in set (0.00 sec)
于 2010-04-16T10:45:07.103 に答える
1
SELECT * FROM TABLE WHERE DATE LIKE '4/%/10'

これにより、2010年4月のすべてのデータが得られます

同様に、uは月の数値、つまりこの場合は4を指定することにより、任意の月のデータを取得できます。

于 2010-04-16T08:08:34.983 に答える