MySQL多个子查询,在日期间隔

时间:2015-11-27 11:05:20

标签: php mysql date

我一直坚持以下查询,并且无法弄清楚如何做到这一点(以下说明):

SELECT 
a.id, a.name, t.agency_id, t.initial_amount,
DATE_FORMAT(t.created_at, "%d.%m.%Y") as date,
DATE_FORMAT(t.created_at, "%Y-%m-%d") as date_created,
t.created_at, t.collection, t.pay, (t.initial_amount + t.collection - t.pay) as total_amount
FROM (
 SELECT
    hh.agency_id, hh.amount, h0.initial_amount, hh.created_at,
    SUM(IF(hh.payment_type=0,hh.amount,0)) AS collection,
    SUM(IF(hh.payment_type=1,hh.amount,0)) AS pay
 FROM house_register AS hh
 LEFT JOIN (
    SELECT h1.initial_amount, h1.agency_id, h1.created_at 
    FROM house_register AS h1
    INNER JOIN (
        SELECT min(h2.id) AS min_id, h2.agency_id, h2.created_at
        FROM house_register AS h2 
        GROUP BY h2.agency_id
    ) AS min_id_ag
        ON h1.agency_id = min_id_ag.agency_id
        AND h1.id = min_id_ag.min_id
) AS h0 
    ON hh.agency_id = h0.agency_id
WHERE hh.created_at BETWEEN '2015-11-01' AND '2015-11-30' 
GROUP BY hh.created_at, hh.agency_id WITH ROLLUP
) AS t 
INNER JOIN agencies as a
on a.id = t.agency_id

所以,我在这里尝试实现的是从单个表中获取某段时间的报告,在此表中我的操作具有类型状态(付款或收款)并且每个操作对应到agency_id(商店)。

我的报告必须是这样的:

列:

agency_id    date X  initial_amount_of_first_transaction_of_day_in_loop sum(payments) sum(collection)

行看起来像这样:

agency_1 2015-01-01 500 100 0
agency_2 2015-01-01 600 100 0
.... next date
agency_1 2015-01-02 600 0 150
agency_2 2015-01-02 450 0 150
etc

我想要的是获取按min(id)agency_id分组的每个日期的第一个事务的initial_amount(因此created_at)。例如,如果我在2015-01-01的日期有50笔交易,我想获得该日期第一笔交易的第initial_amount栏的价值。

现在它只选择整个日期间隔的最小值。我和所有日期的最小值相同。

希望我足够清楚。

谢谢你的帮助!

更新结构:

CREATE TABLE IF NOT EXISTS `house_register` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`created_at` date DEFAULT NULL,
`created_time` time DEFAULT NULL,
`initial_amount` decimal(14,2) DEFAULT NULL,
`document_type` tinyint(3) unsigned DEFAULT NULL,
`document_id` int(10) unsigned DEFAULT NULL,
`document_number` varchar(100) DEFAULT NULL,
`description` varchar(200) DEFAULT NULL,
`amount` decimal(14,2) DEFAULT NULL,
`final_amount` decimal(14,2) DEFAULT NULL,
`agency_id` int(11) DEFAULT NULL,
`user_id` int(10) DEFAULT NULL,
`payment_type` tinyint(1) DEFAULT NULL COMMENT '0 - incasare, 1 - plata',
`number` varchar(50) DEFAULT NULL,
`debit_account` varchar(45) DEFAULT NULL,
`credit_account` varchar(45) DEFAULT NULL,
`short_desc` varchar(45) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=34;

使用结果集更新查询细分:

完整的一个返回: Results complete sql

子查询1:Subquery 1 results

SELECT
hh.agency_id, hh.amount, h0.initial_amount, hh.created_at,
SUM(IF(hh.payment_type=0,hh.amount,0)) AS collection,
SUM(IF(hh.payment_type=1,hh.amount,0)) AS pay
FROM house_register AS hh
LEFT JOIN (
SELECT h1.initial_amount, h1.agency_id, h1.created_at 
FROM house_register AS h1
INNER JOIN (
    SELECT min(h2.id) AS min_id, h2.agency_id, h2.created_at
    FROM house_register AS h2 
    GROUP BY h2.agency_id
) AS min_id_ag
    ON h1.agency_id = min_id_ag.agency_id
    AND h1.id = min_id_ag.min_id
) AS h0 
ON hh.agency_id = h0.agency_id
WHERE hh.created_at BETWEEN '2015-11-01' AND '2015-11-30' 
GROUP BY hh.created_at, hh.agency_id WITH ROLLUP;

子查询2:参见评论

SELECT h1.initial_amount, h1.agency_id, h1.created_at 
FROM house_register AS h1
INNER JOIN (
    SELECT min(h2.id) AS min_id, h2.agency_id, h2.created_at
    FROM house_register AS h2 
    GROUP BY h2.agency_id
) AS min_id_ag
    ON h1.agency_id = min_id_ag.agency_id
    AND h1.id = min_id_ag.min_id;

子查询3:见评论

SELECT min(h2.id) AS min_id, h2.agency_id, h2.created_at
    FROM house_register AS h2 
    GROUP BY h2.agency_id;

3 个答案:

答案 0 :(得分:0)

我相信您需要将日期(created_at)添加到组中,并将日期之间的where子句添加到组中。

        WHERE h2.created_at BETWEEN '2015-11-01' AND '2015-11-30' 
        GROUP BY h2.agency_id, date_format(h2.created_at, "%Y-%b-%d")

第一行将搜索条件缩减到您想要的日期。 第二行按agency_id对所有内容进行分组,然后是当天(通过对created_at格式化的YYY-MM-DD进行分组。

即。类似的东西(我没有测试过但是......)

SELECT 
a.id, a.name, t.agency_id, t.initial_amount,
DATE_FORMAT(t.created_at, "%d.%m.%Y") as date,
DATE_FORMAT(t.created_at, "%Y-%m-%d") as date_created,
t.created_at, t.collection, t.pay, (t.initial_amount + t.collection - t.pay) as total_amount
FROM (
 SELECT
    hh.agency_id, hh.amount, h0.initial_amount, hh.created_at,
    SUM(IF(hh.payment_type=0,hh.amount,0)) AS collection,
    SUM(IF(hh.payment_type=1,hh.amount,0)) AS pay
 FROM house_register AS hh
 LEFT JOIN (
    SELECT h1.initial_amount, h1.agency_id, h1.created_at 
    FROM house_register AS h1
    INNER JOIN (
        SELECT min(h2.id) AS min_id, h2.agency_id, h2.created_at
        FROM house_register AS h2 
        WHERE h2.created_at BETWEEN '2015-11-01' AND '2015-11-30' 
        GROUP BY h2.agency_id, date_format(h2.created_at, "%Y-%b-%d")
    ) AS min_id_ag
        ON h1.agency_id = min_id_ag.agency_id
        AND h1.id = min_id_ag.min_id
) AS h0 
    ON hh.agency_id = h0.agency_id
WHERE hh.created_at BETWEEN '2015-11-01' AND '2015-11-30' 
GROUP BY hh.created_at, hh.agency_id WITH ROLLUP
) AS t 
INNER JOIN agencies as a
on a.id = t.agency_id

答案 1 :(得分:0)

对不起,是的,我不得不重新阅读你的问题几次,但我想我已经把它排序了。这能为您提供所需的结果吗?

对于min(h2.id)选择,您还需要group by h2.created_at,而不仅仅是第{18}行的h2.agency_id - 完整群组= GROUP BY h2.agency_id, h2.created_at

SELECT 
a.id, a.name, t.agency_id, t.initial_amount,
DATE_FORMAT(t.created_at, "%d.%m.%Y") as date,
DATE_FORMAT(t.created_at, "%Y-%m-%d") as date_created,
t.created_at, t.collection, t.pay, (t.initial_amount + t.collection - t.pay) as total_amount
FROM (
 SELECT
    hh.agency_id, hh.amount, h0.initial_amount, hh.created_at,
    SUM(IF(hh.payment_type=0,hh.amount,0)) AS collection,
    SUM(IF(hh.payment_type=1,hh.amount,0)) AS pay
 FROM house_register AS hh
 LEFT JOIN (
    SELECT h1.initial_amount, h1.agency_id, h1.created_at 
    FROM house_register AS h1
    INNER JOIN (
        SELECT min(h2.id) AS min_id, h2.agency_id, h2.created_at
        FROM house_register AS h2 
        GROUP BY h2.agency_id, h2.created_at
    ) AS min_id_ag
        ON h1.agency_id = min_id_ag.agency_id
        AND h1.id = min_id_ag.min_id
) AS h0 
    ON hh.agency_id = h0.agency_id
WHERE hh.created_at BETWEEN '2015-11-01' AND '2015-11-30' 
GROUP BY hh.created_at, hh.agency_id WITH ROLLUP
) AS t 
INNER JOIN agencies as a
on a.id = t.agency_id

答案 2 :(得分:0)

你回答几乎是正确的,肯定让我在正确的轨道上修复它。 非常感谢你的帮助和耐心@wkdmarty!

这是我想要的查询。

SELECT     a.id, 
       a.NAME, 
       t.agency_id, 
       t.initial_amount, 
       Date_format(t.created_at, "%d.%m.%Y") AS date, 
       Date_format(t.created_at, "%Y-%m-%d") AS date_created, 
       t.created_at, 
       t.collection, 
       t.pay, 
       (t.initial_amount + t.collection - t.pay) AS total_amount 
FROM       ( 
                 SELECT    hh.agency_id, 
                           hh.amount, 
                           h0.initial_amount, 
                           hh.created_at, 
                           sum(IF(hh.payment_type=0,hh.amount,0)) AS collection, 
                           sum(IF(hh.payment_type=1,hh.amount,0)) AS pay 
                 FROM      house_register                         AS hh 
                 LEFT JOIN 
                           ( 
                                      SELECT     h1.initial_amount, 
                                                 h1.agency_id, 
                                                 h1.created_at 
                                      FROM       house_register AS h1 
                                      INNER JOIN 
                                                 ( 
                                                          SELECT   min(h2.id) AS min_id, 
                                                                   h2.agency_id, 
                                                                   h2.created_at 
                                                          FROM     house_register AS h2 
                                                          GROUP BY h2.agency_id, 
                                                                   h2.created_at ) AS min_id_ag
                                      ON         h1.agency_id = min_id_ag.agency_id 
                                      AND        h1.id = min_id_ag.min_id 
                                      WHERE      h1.created_at BETWEEN '2015-11-01' AND '2015-11-30' ) AS h0 
                 ON        hh.agency_id = h0.agency_id 
                 AND       hh.created_at = h0.created_at 
                 WHERE     h0.created_at BETWEEN '2015-11-01' AND '2015-11-30' 
                 GROUP BY  hh.created_at, 
                           hh.agency_id WITH rollup ) AS t 
INNER JOIN agencies AS a 
ON a.id = t.agency_id 
ORDER BY t.agency_id, 
         t.created_at