使用join和group by从三个表中获取值

时间:2017-12-22 07:32:41

标签: mysql join group-by

我有三张桌子,financial_years,house_details,consumer_details。我在Sqlfiddle中添加了我的模式:http://sqlfiddle.com/#!9/dd527d/2并且由于下面给出的长度,我的预期结果被包装。我试过的查询是。

查询:

SELECT c.consumer_name as Name
      ,c.house_number
      ,c.address
      ,sum(CASE WHEN h.subincome = 'Garbage tax' THEN f.garbage_tax else 0 end) - 
      sum(CASE WHEN h.subincome = 'Garbage tax' THEN h.rupees else 0 END) as gtax
      ,sum(CASE WHEN h.subincome = 'House tax' THEN f.house_tax else 0 end) - 
      sum(CASE WHEN h.subincome = 'House tax' THEN h.rupees else 0 END) as htax, 
      ,sum(CASE WHEN h.subincome = 'Light tax' THEN f.light_tax else 0 end) - 
      sum(CASE WHEN h.subincome = 'Light tax' THEN h.rupees else 0 END) as LTAX 
from house_details h 
INNER JOIN financial_year f ON h.financial_year = f.year 
                            AND h.house_id = f.house_number
INNER JOIN consumer_details c ON h.house_id = c.house_number 
                              AND h.financial_year != '2017-2018' 
GROUP BY c.consumer_name
        ,c.house_number
        ,c.address

预期结果:

sid | name | house_no | address | arrears
---------------------------------------------------------------------
                                  house_tax | light_tax | garbage_tax
---------------------------------------------------------------------
22    Bala   22         Mumbai    145         710         450 
25    Kannan 25         Pune      704         803         630
2     Arul   2          Delhi     60          570         590

current                             | total
------------------------------------------------------------------------
house_tax | light_tax | garbage_tax | house_tax | light_tax | garbage_tax
------------------------------------------------------------------------
300         400         500           445         1110        950
550         567         543           1254        1370        1173
700         800         900           760         1370        1490

 receipt_no                            | collection
------------------------------------------------------------------------
house_tax  |  light_tax  | garbage_tax | house_tax | light_tax | garbage_tax
------------------------------------------------------------------------
312,313,314   309,310,311   288,304,308  400         540         484
407,408,409   404,405,406   401,402,403  921         915         905                                
410           -             -            500         0           0

 balance
------------------------------------
house_tax | light_tax | garbage_tax 
------------------------------------
45          570         466         
333         455         268         
260         1370        1490         

3 个答案:

答案 0 :(得分:1)

如果数字大于您的预期,那么这里有解释和线索:

JOINing时,中间行数会膨胀。随后的GROUP BY会缩小行数。问题是聚合(例如SUM())是通过膨胀的行数来完成的。

所以诀窍是在执行SUMs之前执行JOIN。尝试像

这样的东西
SELECT ...  -- probably no SUM() needed here
    FROM ( SELECT financial_year, house_id,
                  SUM(...), SUM(...) ... FROM house_details
              GROUP BY 1,2 ) AS h
    JOIN ( SELECT year, house_number, 
                  SUM(...), SUM(...) ... FROM financial_years
              GROUP BY 1,2 ) AS f
        ON h.financial_year = f.year 
       AND h.house_id = f.house_number

我认为最后你不需要GROUP BY

您最后可能需要额外的JOIN来获取customer_name等。并选择ORDER BY customer_name

答案 1 :(得分:1)

这就是我所拥有的。它产生了我认为的正确结果:

SELECT c.consumer_id, c.consumer_name, c.house_number, c.address,
   SUM(GTAX) AS GTAX, SUM(HTAX) AS HTAX, SUM(LTAX) AS LTAX
FROM
(
SELECT c.address, c.consumer_id, c.consumer_name, c.house_number, hd.financial_year, 
  sum(ifnull(f.garbage_tax,0))-ifnull((SELECT SUM(RUPEES) RUPEES FROM house_details h WHERE hd.financial_year=h.financial_year and c.house_number=h.house_id and h.SUBINCOME='Garbage tax'),0) AS gtax, 
  sum(ifnull(f.house_tax,0))-ifnull((SELECT SUM(RUPEES) RUPEES FROM house_details h WHERE hd.financial_year=h.financial_year and  c.house_number=h.house_id and h.SUBINCOME='House tax'),0) AS htax, 
  sum(ifnull(f.light_tax,0))-ifnull((SELECT SUM(RUPEES) RUPEES FROM house_details h WHERE hd.financial_year=h.financial_year and  c.house_number=h.house_id and h.SUBINCOME='Light tax'),0) AS ltax 
from consumer_details c
cross join (select distinct hd.financial_year from house_details hd where hd.financial_year<>'2017-2018') hd
LEFT OUTER JOIN financial_years f ON c.house_number=f.house_number and f.year=hd.financial_year
  where c.house_number in (select h.house_id from house_details h)
group by consumer_id, consumer_name, c.house_number, hd.financial_year
) c
group by c.consumer_id, c.consumer_name, c.house_number, c.address
        ,c.house_number
        ,c.address

答案 2 :(得分:0)

借助Stackoverflow用户的支持,我找到了解决方案。

SELECT
    sid,
    NAME,
    housenu AS house_number,
    addr AS Address,
    htax AS Arrear_housetax,
    ltax AS Arrear_lighttax,
    gtax AS Arrear_garbagetax,
    chousetax AS Current_housetax,
    clighttax AS Current_lighttax,
    cgarbage AS Current_garbagetax,
    htax + chousetax AS totalhousetax,
    ltax + clighttax AS totallighttax,
    gtax + cgarbage AS totalgarbagetax,
    housetax_Ids,
    Garbagetax_ids,
    lighttax_Ids,
    htax_collected AS Collected_housetax,
    LTAX_collected AS Collected_lighttax,
    gtax_collected AS Collected_garbagetax,
    totalhousetax - htax_collected AS balance_housetax,
    totallighttax - LTAX_collected AS balance_Lighttax,
    totalgarbage - gtax_collected AS balance_garbagetax
FROM
    (
    SELECT
        sid,
        NAME,
        housenu,
        addr,
        gtax,
        htax,
        ltax,
        cgarbage,
        chousetax,
        clighttax,
        gtax + cgarbage AS totalgarbage,
        htax + chousetax AS totalhousetax,
        ltax + clighttax AS totallighttax,
        Garbagetax_ids,
        lighttax_Ids,
        housetax_Ids,
        gtax_collected,
        htax_collected,
        LTAX_collected
    FROM
        (
        SELECT
            sid,
            c.consumer_name AS NAME,
            s.house_number AS housenu,
            c.address AS addr,
            SUM(
                CASE WHEN subincome = 'garbage tax' THEN taxdue ELSE 0
            END
    ) - SUM(
        CASE WHEN subincome = 'garbage tax' THEN taxpaid ELSE 0
    END
) AS gtax,
SUM(
    CASE WHEN subincome = 'house tax' THEN taxdue ELSE 0
END
) - SUM(
    CASE WHEN subincome = 'house tax' THEN taxpaid ELSE 0
END
) AS htax,
SUM(
    CASE WHEN subincome = 'light tax' THEN taxdue ELSE 0
END
) - SUM(
    CASE WHEN subincome = 'light tax' THEN taxpaid ELSE 0
END
) AS ltax,
cgarbage,
chousetax,
clighttax,
Garbagetax_ids,
lighttax_Ids,
housetax_Ids,
gtax_collected,
htax_collected,
LTAX_collected
FROM
    (
    SELECT
        F.`house_number`,
        F.`year`,
        F.`house_tax` taxdue,
        F.`createdAt`,
        F.`updatedAt`,
        IFNULL(h.subincome, 'house_tax') subincome,
        IFNULL(H.RUPEES, 0) taxpaid
    FROM
        FINANCIAL_YEARS F
    LEFT JOIN house_details H ON
        H.HOUSE_ID = F.HOUSE_NUMBER AND H.SUBINCOME = 'house tax' AND f.year = h.financial_year
        #where f.house_number = 22
    UNION ALL
SELECT
    F.`house_number`,
    F.`year`,
    F.`light_tax`,
    F.`createdAt`,
    F.`updatedAt`,
    IFNULL(h.subincome, 'light tax'),
    IFNULL(H.RUPEES, 0)
FROM
    FINANCIAL_YEARS F
LEFT JOIN house_details H ON
    H.HOUSE_ID = F.HOUSE_NUMBER AND H.SUBINCOME = 'light tax' AND f.year = h.financial_year
    #where f.house_number = 2
UNION ALL
SELECT
    F.`house_number`,
    F.`year`,
    F.`garbage_tax`,
    F.`createdAt`,
    F.`updatedAt`,
    IFNULL(h.subincome, 'garbage tax'),
    IFNULL(H.RUPEES, 0)
FROM
    FINANCIAL_YEARS F
LEFT JOIN house_details H ON
    H.HOUSE_ID = F.HOUSE_NUMBER AND H.SUBINCOME = 'garbage tax' AND f.year = h.financial_year
    #where f.house_number = 2
) s
LEFT JOIN(
    SELECT house_number,
        IFNULL(garbage_tax, 0) AS cgarbage,
        IFNULL(light_tax, 0) AS clighttax,
        IFNULL(house_tax, 0) AS chousetax
    FROM
        financial_years
    WHERE
        YEAR = "2017-2018"
) Y
ON
    s.house_number = Y.house_number
LEFT JOIN(
    SELECT
        house_id,
        GROUP_CONCAT(garbagetax_Ids) AS Garbagetax_ids,
        GROUP_CONCAT(lighttax_Ids) AS Lighttax_ids,
        GROUP_CONCAT(housetax_Ids) AS Housetax_ids
    FROM
        (
        SELECT
            house_id,
            CASE WHEN subincome = 'Garbage tax' THEN receipt_id
    END AS garbagetax_Ids,
    CASE WHEN subincome = 'Light tax' THEN receipt_id
END AS lighttax_Ids,
CASE WHEN subincome = 'House tax' THEN receipt_id
END AS housetax_Ids
FROM
    house_details
) AS mm
GROUP BY
    house_id
) f
ON
    s.house_number = f.house_id
LEFT JOIN(
    SELECT
        house_id,
        SUM(gtax) AS gtax_collected,
        SUM(htax) AS htax_collected,
        SUM(LTAX) AS LTAX_collected
    FROM
        (
        SELECT
            house_id,
            CASE WHEN h.subincome = 'Garbage tax' THEN SUM(h.rupees) ELSE 0
    END AS gtax,
    CASE WHEN h.subincome = 'House tax' THEN SUM(h.rupees) ELSE 0
END AS htax,
CASE WHEN h.subincome = 'Light tax' THEN SUM(h.rupees) ELSE 0
END AS LTAX
FROM
    house_details h
GROUP BY
    house_id,
    subincome
) AS main
GROUP BY
    house_id
) cf
ON
    s.house_number = cf.house_id

LEFT JOIN(
    SELECT house_number AS sid,
        consumer_name,
        address
    FROM
        consumer_details
) c
ON
    s.house_number = c.sid
WHERE
    s.year <> '2017-2018'
GROUP BY
    c.consumer_name,
    s.house_number,
    c.address
) az
) aa