Group byおよびgroup_concatに関連するデータを毎月表示する結合テーブルクエリに行き詰まっており、ポインタが必要です。
これが簡単なクライアントテーブルです。
-------------------------------- id |名前 1 |ソニー 2 |東芝 3 |アップル 4 | LG 5 | Uco
次に、イベントテーブル
-------------------------------- id | client_id | date_start 1 | 1 | 2017-01-12 18:44:42 2 | 1 | 2017-01-13 18:44:42 3 | 1 | 2017-01-14 18:44:42 4 | 1 | 2017-02-12 18:44:42 5 | 1 | 2017-03-12 18:44:42 6 | 1 | 2017-07-12 18:44:42 7 | 2 | 2017-02-12 18:44:42 8 | 2 | 2017-03-12 18:44:42 9 | 2 | 2017-04-12 18:44:42 10 | 3 | 2017-01-12 18:44:42 11 | 3 | 2017-01-14 18:44:42 12 | 3 | 2017-01-20 18:44:42 13 | 3 | 2017-03-12 18:44:42 14 | 3 | 2017-05-12 18:44:42 15 | 3 | 2017-06-12 18:44:42 16 | 4 | 2017-07-12 18:44:42 17 | 4 | 2017-07-20 18:44:42 18 | 5 | 2017-09-12 18:44:42 19 | 5 | 2017-10-12 18:44:42 20 | 5 | 2017-03-12 18:44:42
望ましい結果は次のとおりです。文字列番号、たとえばJan/Appleの(10-01-12)は、id-month-dayとしてフォーマットされます。
私がこれまでに行ったことは、毎月結果を分割するケースを使用することです
select * from( select e.id、c.name as client、 (CASE WHEN MONTH(e.date_start)= 1 then GROUP_CONCAT(CONCAT(e.id、 '-'、LPAD(month(date_start)、2、 '0')、 '-'、LPAD(day(date_start)、2、 '0'))SEPARATOR '、')END)としてjan、 (CASE WHEN MONTH(e.date_start)= 2 then GROUP_CONCAT(CONCAT(e.id、 '-'、LPAD(month(date_start)、2、 '0')、 '-'、LPAD(day(date_start)、 2、 '0'))SEPARATOR '、')END)as feb、 (CASE WHEN MONTH(e.date_start)= 3 then GROUP_CONCAT(CONCAT(e.id、 '-'、LPAD(month( date_start)、2、 '0')、 '-'、LPAD(day(date_start)、2、 '0'))SEPARATOR '、')END)as mar、 (CASE WHEN MONTH(e。 date_start)= 4 then GROUP_CONCAT(CONCAT(e.id、 '-'、LPAD(month(date_start)、2、 '0')、 '-'、LPAD(day(date_start)、2、 '0'))SEPARATOR '、')END)as apr、 (CASE WHEN MONTH(e.date_start)= 5 then GROUP_CONCAT(CONCAT(e.id、 '-'、LPAD(month(date_start)、2、 '0' )、 '-'、LPAD(day(date_start)、2、 '0'))SEPARATOR '、')END)として、 (CASE WHEN MONTH(e.date_start)= 6 then GROUP_CONCAT(CONCAT (e.id、 '-'、LPAD(month(date_start) 、2、 '0')、 '-'、LPAD(day(date_start)、2、 '0'))SEPARATOR '、')END)as jun、 (CASE WHEN MONTH(e.date_start) = 7次にGROUP_CONCAT(CONCAT(e.id、 '-'、LPAD(month(date_start)、2、 '0')、 '-'、LPAD(day(date_start)、2、 '0'))SEPARATOR '、 ')END)as jul、 (CASE WHEN MONTH(e.date_start)= 8 then GROUP_CONCAT(CONCAT(e.id、'-'、LPAD(month(date_start)、2、' 0 '))、 '-'、LPAD(day(date_start)、2、 '0'))SEPARATOR '、')END)as aug、 (CASE WHEN MONTH(e.date_start)= 9 then GROUP_CONCAT(CONCAT(e .id、 '-'、LPAD(month(date_start)、2、 '0')、 '-'、LPAD(day(date_start)、2、 '0'))SEPARATOR '、')END)as sep、 (CASE WHEN MONTH(e.date_start)= 10 then GROUP_CONCAT(CONCAT(e.id、 '-'、LPAD(month(date_start)、2、 '0')、 '-'、LPAD(day( date_start)、2、 '0'))SEPARATOR '、')END)as oct、 (CASE WHEN MONTH(e.date_start)= 11 then GROUP_CONCAT(CONCAT(e.id、 '-'、LPAD (month(date_start)、2、 '0')、 '-'、LPAD(day(date_start)、2、 '0'))SEPARATOR '、')END)as nov、 (CASE WHEN MONTH MONTH (e.date_start)= 12 then GROUP_CONCAT(CONCAT(e.id、 '-'、LPAD(month( date_start)、2、 '0')、 '-'、LPAD(day(date_start)、2、 '0'))SEPARATOR '、')END)as `dec` from eとしてのイベント は、c.id = e.client_id group by month(date_start)、client order by client )t
ただし、上記のクエリでは、クライアントごとにグループ化するための最終的な調整が必要です。上記の目的のテーブルにカンマを区切り文字として表示して、group by clientの結果を連結するにはどうすればよいですか?
2番目の部分は、各データの合計を毎月数えることです。それほど重要ではありませんが、私は本当にパート1を動作させる必要があります。
どんな助けや提案も大歓迎です。ありがとうございました。
データとテーブルのSQLは次のとおりです。
CREATE TABLE `client`( ` id` int(11)unsigned NOT NULL AUTO_INCREMENT、 `name` varchar(128)DEFAULT NULL、 PRIMARY KEY ( `id`) )ENGINE = InnoDB DEFAULT CHARSET = utf8; LOCK TABLES` client` WRITE; INSERT INTO `client`(` id`、 `name`) VALUES (1、 'Sony')、 (2、 'Toshiba')、 (3、 'Apple')、 (4、 'LG')、 (5、 'Uco'); UNLOCK TABLES; CREATE TABLE `event`( ` id` int(11)unsigned NOT NULL AUTO_INCREMENT、 `client_id` int(11)unsigned DEFAULT NULL、 `date_start` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00'、 PRIMARY KEY(` id`)、 KEY `client_id` ( `client_id`)、 KEY` date_start`( `date_start`) )ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; LOCK TABLES` event` WRITE ; INSERT INTO `event`(` id`、 `client_id`、` date_start`) VALUES (1,1、 」 2017-01-12 18:44:42 ')、 (2,1、' 2017-01-13 18:44:42 ')、 (3,1、' 2017- 01-14 18:44:42 ')、 (4,1、' 2017-02-12 18:44:42 ')、 (5,1、' 2017-03- 12 18:44:42 ')、 (6,1、' 2017-07-12 18:44:42 ')、 (7,2、' 2017-02-12 18 :44:42 ')、 (8,2、' 2017-03-12 18:44:42 ')、 (9,2、' 2017-04-12 18:44 :42 ')、 (10,3、' 2017-01-12 18:44:42 ')、 (11,3、' 2017-01-14 18:44:42 ')、 (12,3、' 2017-01-20 18:44:42 ')、 (13,3、' 2017-03-12 18:44:42 ') 、 (14,3、 '2017-05-12 18:44:42')、 (15,3、 '2017-06-12 18:44:42')、 (16,4、 '2017-07-12 18:44:42')、 (17,4、 '2017-07-20 18:44:42')、 (18,5、 '2017-09-12 18:44:42')、 (19,5、 '2017-10-12 18:44:42')、 (20,5、 '2017-03-12 18:44:42'); UNLOCK TABLES;
この種類の変換(行から列へ)はpivotingと呼ばれます。あなたの場合も要件であると思われるように、データを集約と同時にピボットするのが一般的です。 SQLでは、両方の操作を単一の論理ステップとして実行できます。他のSQL製品はピボット用の特別な構文拡張を提供していますが、より一般的な構文を使用してそれを行う方法があります。これは、少なくともMySQLを含むすべての主要なRDBMSでサポートされています。
このメソッドは条件付き集計と呼ばれ、ほとんど釘付けになっています。クエリのCASE式として実装された条件は、集計関数の内側に行くことになっていますと、条件がチェックしている基準(MONTH(e.date_start)
あなたの場合)は、GROUP BYからexcludedである必要があります。
したがって、代わりに
_SELECT
CASE WHEN MONTH(e.date_start) = 1 THEN GROUP_CONCAT(...),
...
FROM
...
GROUP BY
MONTH(e.date_start),
client
_
そのはず
_SELECT
GROUP_CONCAT(CASE WHEN MONTH(e.date_start) = 1 THEN ...),
...
FROM
...
GROUP BY
MONTH(e.date_start),
client
_
除外部分は直感に反するように見えるかもしれません-結局のところ、あなたは月次データを取得するつもりです。ただし、SQLではrowsをグループ化していることに注意してください。あなたの場合、1つの行は1つのクライアントであるため、グループ化はクライアントのみで行う必要があります。毎月のグループ化は、条件付き集計のみによって実装されるため、暗黙的であると言えます。
とにかく、最後の行はどうですか?最後の行は特別なものであり、それがロールアップ行であるだけではなく、したがって、セット全体の集計データを表します。私の見解では、まったく異なるデータが含まれているため、これはさらに特別です。つまり、連結された文字列ではなくカウントです。
その事実に基づいて、最後の行の結果を取得するために、明確な論理ステップ(個別のSELECT)を検討するのは自然なことのようです。次に、UNION ALL演算子を使用して、2つの結果セットが1つに結合されます。私の意見では、このアプローチはロジックを明確にするでしょう。出力のさまざまな種類のデータは、クエリのさまざまなレッグによって説明されます。そして明確なロジックは、最終的にメンテナンスの容易さを意味します。
したがって、上記のすべてを考慮すると、完全なクエリは次のようになります。
_SELECT
c.name AS client,
GROUP_CONCAT(CASE MONTH(e.date_start) WHEN 1 THEN CONCAT(e.id, '-', RIGHT(DATE(e.date_start), 5)) END SEPARATOR ',') AS jan,
GROUP_CONCAT(CASE MONTH(e.date_start) WHEN 2 THEN CONCAT(e.id, '-', RIGHT(DATE(e.date_start), 5)) END SEPARATOR ',') AS feb,
GROUP_CONCAT(CASE MONTH(e.date_start) WHEN 3 THEN CONCAT(e.id, '-', RIGHT(DATE(e.date_start), 5)) END SEPARATOR ',') AS mar,
GROUP_CONCAT(CASE MONTH(e.date_start) WHEN 4 THEN CONCAT(e.id, '-', RIGHT(DATE(e.date_start), 5)) END SEPARATOR ',') AS apr,
GROUP_CONCAT(CASE MONTH(e.date_start) WHEN 5 THEN CONCAT(e.id, '-', RIGHT(DATE(e.date_start), 5)) END SEPARATOR ',') AS may,
GROUP_CONCAT(CASE MONTH(e.date_start) WHEN 6 THEN CONCAT(e.id, '-', RIGHT(DATE(e.date_start), 5)) END SEPARATOR ',') AS jun,
GROUP_CONCAT(CASE MONTH(e.date_start) WHEN 7 THEN CONCAT(e.id, '-', RIGHT(DATE(e.date_start), 5)) END SEPARATOR ',') AS jul,
GROUP_CONCAT(CASE MONTH(e.date_start) WHEN 8 THEN CONCAT(e.id, '-', RIGHT(DATE(e.date_start), 5)) END SEPARATOR ',') AS aug,
GROUP_CONCAT(CASE MONTH(e.date_start) WHEN 9 THEN CONCAT(e.id, '-', RIGHT(DATE(e.date_start), 5)) END SEPARATOR ',') AS sep,
GROUP_CONCAT(CASE MONTH(e.date_start) WHEN 10 THEN CONCAT(e.id, '-', RIGHT(DATE(e.date_start), 5)) END SEPARATOR ',') AS oct,
GROUP_CONCAT(CASE MONTH(e.date_start) WHEN 11 THEN CONCAT(e.id, '-', RIGHT(DATE(e.date_start), 5)) END SEPARATOR ',') AS nov,
GROUP_CONCAT(CASE MONTH(e.date_start) WHEN 12 THEN CONCAT(e.id, '-', RIGHT(DATE(e.date_start), 5)) END SEPARATOR ',') AS `dec`
FROM
event AS e
INNER JOIN client AS c ON e.client_id = c.id
GROUP BY
c.name
UNION ALL
SELECT
NULL,
COUNT(MONTH(e.date_start) = 1 OR NULL),
COUNT(MONTH(e.date_start) = 2 OR NULL),
COUNT(MONTH(e.date_start) = 3 OR NULL),
COUNT(MONTH(e.date_start) = 4 OR NULL),
COUNT(MONTH(e.date_start) = 5 OR NULL),
COUNT(MONTH(e.date_start) = 6 OR NULL),
COUNT(MONTH(e.date_start) = 7 OR NULL),
COUNT(MONTH(e.date_start) = 8 OR NULL),
COUNT(MONTH(e.date_start) = 9 OR NULL),
COUNT(MONTH(e.date_start) = 10 OR NULL),
COUNT(MONTH(e.date_start) = 11 OR NULL),
COUNT(MONTH(e.date_start) = 12 OR NULL)
FROM
event AS e
;
_
または、おそらく、このように、コードの繰り返しを排除することで、見た目を少し面倒にしたくない場合:
_SELECT
client,
GROUP_CONCAT(CASE month WHEN 1 THEN item END SEPARATOR ',') AS jan,
GROUP_CONCAT(CASE month WHEN 2 THEN item END SEPARATOR ',') AS feb,
GROUP_CONCAT(CASE month WHEN 3 THEN item END SEPARATOR ',') AS mar,
GROUP_CONCAT(CASE month WHEN 4 THEN item END SEPARATOR ',') AS apr,
GROUP_CONCAT(CASE month WHEN 5 THEN item END SEPARATOR ',') AS may,
GROUP_CONCAT(CASE month WHEN 6 THEN item END SEPARATOR ',') AS jun,
GROUP_CONCAT(CASE month WHEN 7 THEN item END SEPARATOR ',') AS jul,
GROUP_CONCAT(CASE month WHEN 8 THEN item END SEPARATOR ',') AS aug,
GROUP_CONCAT(CASE month WHEN 9 THEN item END SEPARATOR ',') AS sep,
GROUP_CONCAT(CASE month WHEN 10 THEN item END SEPARATOR ',') AS oct,
GROUP_CONCAT(CASE month WHEN 11 THEN item END SEPARATOR ',') AS nov,
GROUP_CONCAT(CASE month WHEN 12 THEN item END SEPARATOR ',') AS `dec`
FROM
(
SELECT
c.name AS client,
MONTH(e.date_start) AS month,
CONCAT(e.id, '-', RIGHT(DATE(e.date_start), 5)) AS item
FROM
event AS e
INNER JOIN client AS c ON e.client_id = c.id
) AS derived
GROUP BY
client
UNION ALL
SELECT
NULL,
COUNT(month = 1 OR NULL),
COUNT(month = 2 OR NULL),
COUNT(month = 3 OR NULL),
COUNT(month = 4 OR NULL),
COUNT(month = 5 OR NULL),
COUNT(month = 6 OR NULL),
COUNT(month = 7 OR NULL),
COUNT(month = 8 OR NULL),
COUNT(month = 9 OR NULL),
COUNT(month = 10 OR NULL),
COUNT(month = 11 OR NULL),
COUNT(month = 12 OR NULL)
FROM
(
SELECT
MONTH(e.date_start) AS month
FROM
event AS e
) AS derived
;
_
_A = B OR NULL
_の式に慣れていない場合は、_CASE WHEN A = B THEN 1 ELSE NULL END
_の代わりと考えてください。実際の動作の詳細については、このスタックオーバーフローの質問を参照してください。
ニースが明確なロジックと保守性について話しているすべてのことにもかかわらず、クエリを単一のSELECTとして実装できるようにしたい場合があります。コードの繰り返しを減らすことで初期バージョンを簡略化できたとしても、各SELECTレッグでそれを必要とするため、MONTH(date_start)
式をクエリ全体で2回指定する必要があります。そして、それでも理由が十分でない場合、代替ソリューションはより速く、場合によっては顕著になるかもしれません。そして、おそらく結果のクエリはあまり醜く見えないでしょう。結局のところ、プレーンでシンプルな選択肢があればいいのです。
では、クライアントの詳細とロールアップ行の両方が同じSELECTステートメントで生成されるように、 WITH ROLLUP を使用してクエリを書き換えることはどのようにできるでしょうか(UNION ALL種類の不正行為はありません)。
さて、前者のソリューションをプロトタイプとして使用できます。そのクエリの一部は、クライアントでグループ連結を実行します。他の部分は、セット全体の行をカウントします。これで、単一部分のクエリが必要な場合は、単一部分が両方のレベルで両方の操作を実行する必要があります。
どのレベルでどの種類の情報を表示するかは、別の条件セットで決定する必要があります。
上記の点を考慮して、シングルステップクエリでの私の試みを次に示します。
_SELECT
client,
IF(client IS NULL, COUNT(month = 1 OR NULL), GROUP_CONCAT(CASE month WHEN 1 THEN item END SEPARATOR ',')) AS jan,
IF(client IS NULL, COUNT(month = 2 OR NULL), GROUP_CONCAT(CASE month WHEN 2 THEN item END SEPARATOR ',')) AS feb,
IF(client IS NULL, COUNT(month = 3 OR NULL), GROUP_CONCAT(CASE month WHEN 3 THEN item END SEPARATOR ',')) AS mar,
IF(client IS NULL, COUNT(month = 4 OR NULL), GROUP_CONCAT(CASE month WHEN 4 THEN item END SEPARATOR ',')) AS apr,
IF(client IS NULL, COUNT(month = 5 OR NULL), GROUP_CONCAT(CASE month WHEN 5 THEN item END SEPARATOR ',')) AS may,
IF(client IS NULL, COUNT(month = 6 OR NULL), GROUP_CONCAT(CASE month WHEN 6 THEN item END SEPARATOR ',')) AS jun,
IF(client IS NULL, COUNT(month = 7 OR NULL), GROUP_CONCAT(CASE month WHEN 7 THEN item END SEPARATOR ',')) AS jul,
IF(client IS NULL, COUNT(month = 8 OR NULL), GROUP_CONCAT(CASE month WHEN 8 THEN item END SEPARATOR ',')) AS aug,
IF(client IS NULL, COUNT(month = 9 OR NULL), GROUP_CONCAT(CASE month WHEN 9 THEN item END SEPARATOR ',')) AS sep,
IF(client IS NULL, COUNT(month = 10 OR NULL), GROUP_CONCAT(CASE month WHEN 10 THEN item END SEPARATOR ',')) AS oct,
IF(client IS NULL, COUNT(month = 11 OR NULL), GROUP_CONCAT(CASE month WHEN 11 THEN item END SEPARATOR ',')) AS nov,
IF(client IS NULL, COUNT(month = 12 OR NULL), GROUP_CONCAT(CASE month WHEN 12 THEN item END SEPARATOR ',')) AS `dec`
FROM
(
SELECT
c.name AS client,
MONTH(e.date_start) AS month,
CONCAT(e.id, '-', RIGHT(DATE(e.date_start), 5)) AS item
FROM
event AS e
INNER JOIN client AS c ON e.client_id = c.id
) AS derived
GROUP BY
client
WITH ROLLUP
;
_
ご覧のとおり、クエリはクライアントレベルとセットレベル全体の両方でCOUNTとGROUP_CONCATの両方を計算しています。ただし、結果の各ペアはIF関数内に配置されるため、最終的には各列で1つまたは他の結果のみが返されます。
チェックする条件は_client IS NULL
_です。 client
がたまたまnullの場合、それは現在のグループがセット全体を表し、その場合、各IF関数がCOUNT結果を選択することを意味します。 client
値がnullでない場合は、クライアントレベルにあり、行の各グループが特定のクライアントを表していることを意味します。その場合、GROUP_CONCATの結果が返されます。これは要件に基づいています。これは、クライアントの場合、連結された文字列を表示する必要があるためです。
両方のソリューションが見つかります atdbfiddle.uk 。
上記の私の説明では、解決策とその機能に焦点を当てようとしました。混乱を避けるために、言及する価値のある特定のアンチパターンをコードに許可しました。
暗黙的にデータを変換する際の優先ルールへの依存
関数COUNT()とGROUP_CONCAT()の結果は異なります。 1つは整数を返し、もう1つは文字列を返します。このようなさまざまなタイプの値を1つの列に入れようとする場合、サーバーはどのタイプを他のどのタイプに変換するかを決定する必要があります。これらのルールを知っておくのは良いことですが、実稼働コードではそれらに依存するべきではありません。それは単に悪い習慣です。
上記のクエリでは、COUNTとGROUP_CONCATは、同じクエリの異なるレッグの同じ列にあるか、2つを選択する同じ条件にあります。いずれの場合も、MySQLは優先タイプのルールを適用する必要があります。これを回避するには、各COUNTを文字列として明示的にキャストします。
_CAST(COUNT(...) AS char)
_
GROUP_CONCATにORDER BYがありません。
ORDER BYを省略した場合、クエリが文字列を_A,B,C
_として返し、もう1つが_B,A,C
_として返し、後で_C,B,A
_として返すかどうかは問題ではないと単に言っているだけです。結果を予測可能にする場合は、常にORDER BYを指定し、結合を回避するために十分な基準を常に使用してください。
上記のクエリでは、行がすでに非常に長くなっているため、提示のために意図的にORDER BYを省略しました。この問題は、次のようなORDER BYで簡単に修正できます。
_ORDER BY item ASC
_
具体的には、GROUP_CONCATでは次のように使用されます。
_GROUP_CONCAT(CASE month WHEN 12 THEN item END ORDER BY item ASC SEPARATOR ',')
_
SELECT IFNULL(month_of_date_start,'Year') month_of_date_start,IFNULL(name,'Total') name
,IF(ISNULL(name)=1,LENGTH(val)-LENGTH(REPLACE(val,',',''))+1,val) key_values
FROM (SELECT A.name,MONTH(B.date_start) month_of_date_start,
GROUP_CONCAT(CONCAT(B.id,'-',DATE_FORMAT(date_start,'%m-%d')) ORDER BY B.id) val
FROM client A LEFT JOIN (SELECT * FROM event
WHERE date_start >= MAKEDATE(2017,1) AND date_start < MAKEDATE(2018,1)) B
ON A.id = B.client_id GROUP BY MONTH(date_start),A.name WITH ROLLUP) AA;
mysql> SELECT IFNULL(month_of_date_start,'Year') month_of_date_start,IFNULL(name,'Total') name
-> ,IF(ISNULL(name)=1,LENGTH(val)-LENGTH(REPLACE(val,',',''))+1,val) key_values
-> FROM (SELECT A.name,MONTH(B.date_start) month_of_date_start,
-> GROUP_CONCAT(CONCAT(B.id,'-',DATE_FORMAT(date_start,'%m-%d')) ORDER BY B.id) val
-> FROM client A LEFT JOIN (SELECT * FROM event
-> WHERE date_start >= MAKEDATE(2017,1) AND date_start < MAKEDATE(2018,1)) B
-> ON A.id = B.client_id GROUP BY MONTH(date_start),A.name WITH ROLLUP) AA;
+---------------------+---------+----------------------------+
| month_of_date_start | name | key_values |
+---------------------+---------+----------------------------+
| 1 | Apple | 10-01-12,11-01-14,12-01-20 |
| 1 | Sony | 1-01-12,2-01-13,3-01-14 |
| 1 | Total | 6 |
| 2 | Sony | 4-02-12 |
| 2 | Toshiba | 7-02-12 |
| 2 | Total | 2 |
| 3 | Apple | 13-03-12 |
| 3 | Sony | 5-03-12 |
| 3 | Toshiba | 8-03-12 |
| 3 | Uco | 20-03-12 |
| 3 | Total | 4 |
| 4 | Toshiba | 9-04-12 |
| 4 | Total | 1 |
| 5 | Apple | 14-05-12 |
| 5 | Total | 1 |
| 6 | Apple | 15-06-12 |
| 6 | Total | 1 |
| 7 | LG | 16-07-12,17-07-20 |
| 7 | Sony | 6-07-12 |
| 7 | Total | 3 |
| 9 | Uco | 18-09-12 |
| 9 | Total | 1 |
| 10 | Uco | 19-10-12 |
| 10 | Total | 1 |
| Year | Total | 20 |
+---------------------+---------+----------------------------+
25 rows in set (0.01 sec)
データを表示することの詳細についてはお任せします
別の年(2012など)を調べたい場合は、単に
WHERE date_start >= MAKEDATE(2017,1) AND date_start < MAKEDATE(2018,1)) B
に
WHERE date_start >= MAKEDATE(2012,1) AND date_start < MAKEDATE(2013,1)) B