2015-10-20 37 views
0

比方說,我有一個表「日曆」MYSQL:左從兩個選擇加入的日期以「填補空白」

+------------+ 
| day_date | 
+------------+ 
| 2015-01-01 | 
| 2015-01-02 | 
| 2015-01-03 | 
| .......... | 
| 2015-07-14 | 
| 2015-07-15 | 
+------------+ 

與此查詢我可以選擇一週(我需要)

SELECT WEEK(day_date,1) AS NUM_WEEK, 
YEAR(day_date) AS YEAR, 
STR_TO_DATE(CONCAT(YEAR(day_date),WEEK(day_date,1),' Monday'), '%X%V %W') AS date_start 
FROM calendar 
GROUP BY NUM_WEEK 

這是結果:

+----------+------+------------+ 
| NUM_WEEK | YEAR | date_start | 
+----------+------+------------+ 
|  29 | 2015 | 2015-07-20 | 
|  30 | 2015 | 2015-07-27 | 
|  31 | 2015 | 2015-08-03 | 
|  32 | 2015 | 2015-08-10 | 
|  33 | 2015 | 2015-08-17 | 
|  34 | 2015 | 2015-08-24 | 
|  35 | 2015 | 2015-08-31 | 
|  36 | 2015 | 2015-09-07 | 
|  37 | 2015 | 2015-09-14 | 
|  38 | 2015 | 2015-09-21 | 
|  39 | 2015 | 2015-09-28 | 
|  40 | 2015 | 2015-10-05 | 
|  41 | 2015 | 2015-10-12 | 
|  42 | 2015 | 2015-10-19 | 
|  43 | 2015 | 2015-10-26 | 
+----------+------+------------+ 

現在我有另一個表:

+----+------------+--------+---------------------+ 
| id | id_account | amount | date_transaction | 
+----+------------+--------+---------------------+ 
| 1 |  283 | 150 | 2015-06-21 15:50:47 | 
| 2 |  283 | 47.74 | 2015-07-23 15:55:44 | 
| 3 |  281 | 21.55 | 2015-08-24 12:27:11 | 
| 4 |  283 | 11.22 | 2015-08-25 10:00:54 | 
+----+------------+--------+---------------------+ 

他們在日期的差距。

有了類似的查詢:

SELECT WEEK(date_transaction,1) AS NUM_WEEK, 
YEAR(date_transaction) AS YEAR, 
STR_TO_DATE(CONCAT(YEAR(date_transaction),WEEK(date_transaction,1),' Monday'), '%X%V %W') 
AS date_start, 
transaction.id_account, 
SUM(amount) as total FROM transaction 
INNER JOIN account ON account.id_account = transaction.id_account 
WHERE amount > 0 AND transaction.id_account 
IN (SELECT id_account FROM account WHERE id_customer = 12) 
GROUP BY id_account, WEEK(date_transaction,1) 

我得到這個結果(可能數據是不準確的,指的是先前的表,只是爲了解釋)。

+----------+------+------------+-----------+----------+ 
| NUM_WEEK | YEAR | date_start | idAccount | total | 
+----------+------+------------+-----------+----------+ 
|  29 | 2015 | 2015-07-20 |  281 | 22377.00 | 
|  30 | 2015 | 2015-07-27 |  281 | 11550.00 | 
|  32 | 2015 | 2015-08-04 |  281 | 4500.00 | 
|  30 | 2015 | 2015-07-27 |  283 | 1500  | 
+----------+------+------------+-----------+----------+ 

我會,右(或左)加入這兩個表?

  1. 的最小(和最大)周,這樣我就可以......(見2)
  2. 填補國內空白與NULL值缺失周。

例如,在一個更復雜的結果集:

+----------+------+------------+-----------+----------+ 
| NUM_WEEK | YEAR | date_start | idAccount | total | 
+----------+------+------------+-----------+----------+ 
|  29 | 2015 | 2015-07-20 |  281 | 22377.00 | 
|  30 | 2015 | 2015-07-27 |  281 | 11550.00 | 
|  31 | 2015 | 2015-07-02 |  281 | NULL  | 
|  32 | 2015 | 2015-08-09 |  281 | 4500.00 | 
|  29 | 2015 | 2015-08-09 |  283 | NULL  | 
|  30 | 2015 | 2015-07-16 |  283 | 1500  | 
|  31 | 2015 | 2015-07-16 |  283 | NULL  | 
|  32 | 2015 | 2015-07-16 |  283 | NULL  | 
+----------+------+------------+-----------+----------+ 

注意,例如,該id = 283現在已在第29周,31和32 NULL,例如,例如像id = 281具有NULL在WEEK 31

我也準備在這裏SQLFiddle:http://sqlfiddle.com/#!9/a8fdc/3

非常感謝你。

回答

1

我看看你的問題,我想出了這個解決方案。以下是您的查詢的樣子:

SELECT t1.NUM_WEEK, t1.`YEAR`, t1.date_start, t1.id_account, t2.total 
FROM (SELECT c.NUM_WEEK, c.`YEAR`, c.date_start, a.id_account 
     FROM (SELECT WEEK(day_date,1) AS NUM_WEEK, 
        YEAR(day_date) AS `YEAR`, 
        STR_TO_DATE(CONCAT(YEAR(day_date),WEEK(day_date,1),' Monday'), '%X%V %W') AS date_start, 
        (SELECT GROUP_CONCAT(id_account) FROM account WHERE id_customer=12) AS accounts_id 
      FROM calendar 
      GROUP BY NUM_WEEK) c 
     INNER JOIN account a 
     ON FIND_IN_SET(a.id_account, c.accounts_id) 
     ORDER BY a.id_account, c.NUM_WEEK) t1 
LEFT JOIN 
    (SELECT WEEK(t.date_transaction,1) AS NUM_WEEK, 
      YEAR(t.date_transaction) AS `YEAR`, 
      STR_TO_DATE(CONCAT(YEAR(t.date_transaction),WEEK(t.date_transaction,1),' Monday'), '%X%V %W') AS date_start, 
      t.id_account, SUM(t.amount) AS total 
     FROM `transaction` t 
     INNER JOIN account a 
     ON a.id_account = t.id_account 
     WHERE t.amount > 0 AND 
      t.id_account IN (SELECT id_account FROM account WHERE id_customer = 12) 
     GROUP BY id_account, WEEK(date_transaction,1)) t2 
ON t1.NUM_WEEK = t2.NUM_WEEK AND t1.YEAR = t2.YEAR AND t1.id_account = t2.id_account; 

這是SQL Fiddle,因此您可以檢查結果。希望你在找什麼。

一點解釋:

首先認爲我做的是我的小修改,你從表日曆中提取數據,並添加有一個新列名爲accounts_id第一個查詢。該查詢現在看起來是這樣的:

SELECT WEEK(day_date,1) AS NUM_WEEK, 
     YEAR(day_date) AS `YEAR`, 
     STR_TO_DATE(CONCAT(YEAR(day_date),WEEK(day_date,1),' Monday'), '%X%V %W') AS date_start, 
     (SELECT GROUP_CONCAT(id_account) FROM account WHERE id_customer=12) AS accounts_id 
FROM calendar 
GROUP BY NUM_WEEK 

請注意在此行中的SELECT語句

(SELECT GROUP_CONCAT(id_account) FROM account WHERE id_customer=12) AS accounts_id 

注意,當你選擇特定客戶需要更改客戶ID在這個線也!

這是Fiddle因此您可以查看該查詢產生的結果。

這是必要的,因爲我們需要連接每個星期與每個帳戶,以獲得所需的結果。

下一步是擴展先前的查詢,以便我們可以分開accounts_id列(查看先前查詢的結果),以便我們可以獲取該列中每個值的行。擴展查詢這個樣子的:

SELECT c.NUM_WEEK, c.`YEAR`, c.date_start, a.id_account 
FROM (SELECT WEEK(day_date,1) AS NUM_WEEK, 
      YEAR(day_date) AS `YEAR`, 
      STR_TO_DATE(CONCAT(YEAR(day_date),WEEK(day_date,1),' Monday'), '%X%V %W') AS date_start, 
      (SELECT GROUP_CONCAT(id_account) FROM account WHERE id_customer=12) AS accounts_id 
     FROM calendar 
     GROUP BY NUM_WEEK) c 
INNER JOIN account a 
ON FIND_IN_SET(a.id_account, c.accounts_id) 
ORDER BY a.id_account, c.NUM_WEEK 

和輸出,你可以在這個Fiddle

看到後,所有我們需要做的就是讓左此查詢之間的連接和查詢你在你的問題已經寫(最後查詢)。

有可能是一個更好的解決方案,甚至這個也許可以提高一點,但我沒有現在太多的時間來處理這個,這是我想到的首先想到......

GLOBAL!

GL!

當你在MySQL中使用保留字如YEAR,TRANSACTION等作爲列名(如列名)..如果必須使用列或表的名稱使用它們可能會導致高音使用反引號() to mark them (as年`)...

+0

每當我認爲你寫了MySQL。太棒了。非常感謝你 – sineverba