汇总和空记录的汇总也

时间:2015-05-20 13:00:52

标签: mysql aggregation

大家好我有3张桌子。 这是创建数据:

CREATE TABLE `positionstyp` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `parent_id` int(11) DEFAULT NULL,
 `bau_nr_komplett` varchar(32) NOT NULL,
 PRIMARY KEY (`id`),
 KEY `parent_id` (`parent_id`),
 CONSTRAINT `positionstyp_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `positionstyp` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB;

CREATE TABLE `projektposition` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `projekt_id` int(11) NOT NULL,
 `preis_vertragskosten` float DEFAULT NULL,
 `positionstyp_id` int(11),
 PRIMARY KEY (`id`),
 KEY `positionstyp_id` (`positionstyp_id`),
 CONSTRAINT `fk_projektposition_positionstypID` FOREIGN KEY (`positionstyp_id`) REFERENCES `positionstyp` (`id`) ON UPDATE CASCADE
) ENGINE=InnoDB;

CREATE TABLE `menge` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `baufortschritt` int(11) NOT NULL DEFAULT 0,
 `menge` float NOT NULL,
 `projektposition_id` int(11) NOT NULL,
 PRIMARY KEY (`id`),
 KEY `projektposition_id` (`projektposition_id`),
 CONSTRAINT `menge_ibfk_10` FOREIGN KEY (`projektposition_id`) REFERENCES `projektposition` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB;

INSERT INTO `positionstyp` (`id`, `parent_id`, `bau_nr_komplett`) VALUES
(1, NULL, '1'),
(2, NULL, '2'),
(3, NULL, '3'),
(4, NULL, '4'),
(5, NULL, '5'),
(6, NULL, '6'),
(7, 3, '325'),
(8, 7, '325.0'),
(9, 7, '325.1'),
(10, 8, '325.0.0');

INSERT INTO `projektposition` (`id`, `projekt_id`, `preis_vertragskosten`, `positionstyp_id`) VALUES
(1, 1325, 100, 3),
(2, 1325, 300, 7),
(3, 1325, 150, 7),
(4, 1325, 200, 10),
(5, 1325, 50, 9);

INSERT INTO `menge` (`id`, `menge`, `baufortschritt`, `projektposition_id`) VALUES
(1, 10, 1, 1),
(2, 20, 20, 2),
(3, 30, 30, 3),
(4, 40, 40, 4),
(5, 50, 100, 5),
(6, 60, 87, 1),
(7, 70, 90, 2),
(8, 80, 10, 3),
(9, 90, 50, 4),
(10, 100, 0, 5),
(11, 1000, 100, 5),
(12, 100, 10, 6);

CREATE TABLE `positionstyp` ( `id` int(11) NOT NULL AUTO_INCREMENT, `parent_id` int(11) DEFAULT NULL, `bau_nr_komplett` varchar(32) NOT NULL, PRIMARY KEY (`id`), KEY `parent_id` (`parent_id`), CONSTRAINT `positionstyp_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `positionstyp` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB; CREATE TABLE `projektposition` ( `id` int(11) NOT NULL AUTO_INCREMENT, `projekt_id` int(11) NOT NULL, `preis_vertragskosten` float DEFAULT NULL, `positionstyp_id` int(11), PRIMARY KEY (`id`), KEY `positionstyp_id` (`positionstyp_id`), CONSTRAINT `fk_projektposition_positionstypID` FOREIGN KEY (`positionstyp_id`) REFERENCES `positionstyp` (`id`) ON UPDATE CASCADE ) ENGINE=InnoDB; CREATE TABLE `menge` ( `id` int(11) NOT NULL AUTO_INCREMENT, `baufortschritt` int(11) NOT NULL DEFAULT 0, `menge` float NOT NULL, `projektposition_id` int(11) NOT NULL, PRIMARY KEY (`id`), KEY `projektposition_id` (`projektposition_id`), CONSTRAINT `menge_ibfk_10` FOREIGN KEY (`projektposition_id`) REFERENCES `projektposition` (`id`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB; INSERT INTO `positionstyp` (`id`, `parent_id`, `bau_nr_komplett`) VALUES (1, NULL, '1'), (2, NULL, '2'), (3, NULL, '3'), (4, NULL, '4'), (5, NULL, '5'), (6, NULL, '6'), (7, 3, '325'), (8, 7, '325.0'), (9, 7, '325.1'), (10, 8, '325.0.0'); INSERT INTO `projektposition` (`id`, `projekt_id`, `preis_vertragskosten`, `positionstyp_id`) VALUES (1, 1325, 100, 3), (2, 1325, 300, 7), (3, 1325, 150, 7), (4, 1325, 200, 10), (5, 1325, 50, 9); INSERT INTO `menge` (`id`, `menge`, `baufortschritt`, `projektposition_id`) VALUES (1, 10, 1, 1), (2, 20, 20, 2), (3, 30, 30, 3), (4, 40, 40, 4), (5, 50, 100, 5), (6, 60, 87, 1), (7, 70, 90, 2), (8, 80, 10, 3), (9, 90, 50, 4), (10, 100, 0, 5), (11, 1000, 100, 5), (12, 100, 10, 6);

“menge”与一个“projektposition”绑定,“projektposition”与一个“positionstyp”绑定。然后“positionstyp”可能有一个父“positionstyp”。

在“menge”中有一个字段“menge”和一个称为“menge”的字段“baufortschritt”。然后字段“preis_vertragskosten”给这个组合一个价格。

所以menge的价格是(menge * mengemenge * baufortschrittprojektposition

在我的SELECT中,我希望所有“positionstyp” - 具有汇总价格的条目以及“positionstyp” - 条目下没有“menge”/“projektposition”,因此没有价格,只有特定的“projekt_id”

我的第一次尝试是group by和rollup,但是没有价格的所有“positionstyp”都失败了。

现在我的代码接近我想要的地方:

preis_vertragskosten

SELECT 
    pt.id, 
    pt.parent_id, 
    SUM(IF(m.menge IS NULL,0, m.menge * p.preis_vertragskosten * m.baufortschritt/100 * (p.projekt_id=1325))) as summe,
    pt.bau_nr_komplett
FROM positionstyp pt
LEFT JOIN projektposition p     ON (p.positionstyp_id=pt.id) 
LEFT JOIN menge m     ON (m.projektposition_id=p.id) 
GROUP BY pt.id

输出正确地总结了menge,但当然没有总结递归positionstyp_parents。 positionstyp-table的递归更容易在SELECT pt.id, pt.parent_id, SUM(IF(m.menge IS NULL,0, m.menge * p.preis_vertragskosten * m.baufortschritt/100 * (p.projekt_id=1325))) as summe, pt.bau_nr_komplett FROM positionstyp pt LEFT JOIN projektposition p ON (p.positionstyp_id=pt.id) LEFT JOIN menge m ON (m.projektposition_id=p.id) GROUP BY pt.id 字段中找到:positionstyp是所有positionstyp的子元素,bs_nr_komplett是child-positionstyp的开头 bau_nr_komplett`(don'但必须是直接的孩子。)

有些人有想法吗?

谢谢和最诚挚的问候, 托拜厄斯

结果现在是:

bau_nr_komplett

期望的结果是:

s

- 编辑2: 我发现一个糟糕的解决方案而糟糕意味着它适用于测试数据集。但是对于真实的数据库和100.000s的数据集,它需要半个小时; D

bau_nr_komplett    summe
              1        0     
              2        0     
              3     5230     
              4        0     
              5        0     
              6        0     
            325    22650     
          325.0        0     
          325.1    52500     
        325.0.0    12200  

1 个答案:

答案 0 :(得分:0)

我找到了自己的答案并添加了一些详细信息:

CREATE PROCEDURE `getProjektsummen`(IN projektID int)
BEGIN
SELECT tttt.id, tttt.parent_id, tttt.bau_nr_komplett, tttt.summe_kostenanschlag, tttt.summe_kostenanschlag_baufortschritt,
tttt.summe_vertragskosten, tttt.summe_vertragskosten_baufortschritt,
tttt.summe_gemittelteangebotskosten, tttt.summe_gemittelteangebotskosten_baufortschritt
FROM (

SELECT id, parent_id,bau_nr_komplett, summe_kostenanschlag, summe_kostenanschlag_baufortschritt,
summe_vertragskosten, summe_vertragskosten_baufortschritt,
summe_gemittelteangebotskosten, summe_gemittelteangebotskosten_baufortschritt
FROM 
(SELECT tt.id, tt.parent_id, tt.bau_nr_komplett, 
MAX(tt.summe_kostenanschlag) as summe_kostenanschlag,MAX(tt.summe_kostenanschlag_baufortschritt) as summe_kostenanschlag_baufortschritt,
MAX(tt.summe_vertragskosten) as summe_vertragskosten,MAX(tt.summe_vertragskosten_baufortschritt) as summe_vertragskosten_baufortschritt,
MAX(tt.summe_gemittelteangebotskosten) as summe_gemittelteangebotskosten,MAX(tt.summe_gemittelteangebotskosten_baufortschritt) as summe_gemittelteangebotskosten_baufortschritt
FROM (
SELECT ptt.id, ptt.parent_id, coalesce(t.sub9,t.sub8,t.sub7,t.sub6,t.sub5,t.sub4,t.sub3,t.sub2,t.sub1) as bau_nr_komplett, 
    ROUND(IFNULL(t.summe_kostenanschlag,0),0) as summe_kostenanschlag,
    ROUND(IFNULL(t.summe_kostenanschlag_baufortschritt,0),0) as summe_kostenanschlag_baufortschritt, 
    ROUND(IFNULL(t.summe_vertragskosten,0),0) as summe_vertragskosten, 
    ROUND(IFNULL(t.summe_vertragskosten_baufortschritt,0),0) as summe_vertragskosten_baufortschritt, 
    ROUND(IFNULL(t.summe_gemittelteangebotskosten,0),0) as summe_gemittelteangebotskosten, 
    ROUND(IFNULL(t.summe_gemittelteangebotskosten_baufortschritt,0),0) as summe_gemittelteangebotskosten_baufortschritt
FROM 
(
SELECT DISTINCT
    sum(menge * preis_kostenanschlag *(p.projekt_id=projektID)) as summe_kostenanschlag,
    sum(menge * preis_kostenanschlag * baufortschritt/100 *(p.projekt_id=projektID)) as summe_kostenanschlag_baufortschritt,
    sum(menge * preis_vertragskosten *(p.projekt_id=projektID)) as summe_vertragskosten,
    sum(menge * preis_vertragskosten * baufortschritt/100 *(p.projekt_id=projektID)) as summe_vertragskosten_baufortschritt,
    sum(menge * preis_gemittelte_angebotskosten *(p.projekt_id=projektID)) as summe_gemittelteangebotskosten,
    sum(menge * preis_gemittelte_angebotskosten * baufortschritt/100 *(p.projekt_id=projektID)) as summe_gemittelteangebotskosten_baufortschritt,
    SUBSTRING(pt.bau_nr_komplett,1,1) as sub1,
    SUBSTRING(pt.bau_nr_komplett,1,2) as sub2,
    SUBSTRING(pt.bau_nr_komplett,1,3) as sub3,
    SUBSTRING(pt.bau_nr_komplett,1,4) as sub4,
    SUBSTRING(pt.bau_nr_komplett,1,5) as sub5,
    SUBSTRING(pt.bau_nr_komplett,1,6) as sub6,
    SUBSTRING(pt.bau_nr_komplett,1,7) as sub7,
    SUBSTRING(pt.bau_nr_komplett,1,8) as sub8,
    SUBSTRING(pt.bau_nr_komplett,1,9) as sub9   
FROM menge m 
    join projektposition p ON (m.projektposition_id=p.id) 
    join positionstyp pt ON (p.positionstyp_id=pt.id)
GROUP BY SUBSTRING(pt.bau_nr_komplett,1,1), 
SUBSTRING(pt.bau_nr_komplett,1,2),
SUBSTRING(pt.bau_nr_komplett,1,3),
SUBSTRING(pt.bau_nr_komplett,1,4),
SUBSTRING(pt.bau_nr_komplett,1,5),
SUBSTRING(pt.bau_nr_komplett,1,6),
SUBSTRING(pt.bau_nr_komplett,1,7),
SUBSTRING(pt.bau_nr_komplett,1,8),
SUBSTRING(pt.bau_nr_komplett,1,9)
WITH ROLLUP
) t join positionstyp ptt on (coalesce(t.sub9,t.sub8,t.sub7,t.sub6,t.sub5,t.sub4,t.sub3,t.sub2,t.sub1) = ptt.bau_nr_komplett)
WHERE 
LENGTH(coalesce(t.sub9,t.sub8,t.sub7,t.sub6,t.sub5,t.sub4,t.sub3,t.sub2,t.sub1))<>2 AND
SUBSTRING(reverse(coalesce(t.sub9,t.sub8,t.sub7,t.sub6,t.sub5,t.sub4,t.sub3,t.sub2,t.sub1)),1,1) <> '.' AND
(
(ISNULL(t.sub9) AND NOT ISNULL(t.sub8) AND LENGTH(t.sub8)=8) OR
(ISNULL(t.sub9) AND ISNULL(t.sub8) AND NOT ISNULL(t.sub7) AND LENGTH(t.sub7)=7) OR
(ISNULL(t.sub9) AND ISNULL(t.sub8) AND ISNULL(t.sub7) AND NOT ISNULL(t.sub6) AND LENGTH(t.sub6)=6) OR
(ISNULL(t.sub9) AND ISNULL(t.sub8) AND ISNULL(t.sub7) AND ISNULL(t.sub6) AND NOT ISNULL(t.sub5) AND LENGTH(t.sub5)=5) OR
(ISNULL(t.sub9) AND ISNULL(t.sub8) AND ISNULL(t.sub7) AND ISNULL(t.sub6) AND ISNULL(t.sub5) AND NOT ISNULL(t.sub4) AND LENGTH(t.sub4)=4) OR
(ISNULL(t.sub9) AND ISNULL(t.sub8) AND ISNULL(t.sub7) AND ISNULL(t.sub6) AND ISNULL(t.sub5) AND ISNULL(t.sub4)AND NOT ISNULL(t.sub3) AND LENGTH(t.sub3)=3) OR
(ISNULL(t.sub9) AND ISNULL(t.sub8) AND ISNULL(t.sub7) AND ISNULL(t.sub6) AND ISNULL(t.sub5) AND ISNULL(t.sub4) AND ISNULL(t.sub3)AND NOT ISNULL(t.sub2) AND LENGTH(t.sub2)=2) OR
(ISNULL(t.sub9) AND ISNULL(t.sub8) AND ISNULL(t.sub7) AND ISNULL(t.sub6) AND ISNULL(t.sub5) AND ISNULL(t.sub4) AND ISNULL(t.sub3) AND ISNULL(t.sub2)AND NOT ISNULL(t.sub1) AND LENGTH(t.sub1)=1))
UNION
SELECT pptt.id as id, pptt.parent_id as parent_id, pptt.bau_nr_komplett as bau_nr_komplett, 
0 as summe_kostenanschlag,
0 as summe_kostenanschlag_baufortschritt,
0 as summe_vertragskosten,
0 as summe_vertragskosten_baufortschritt,
0 as summe_gemittelteangebotskosten,
0 as summe_gemittelteangebotskosten_baufortschritt
FROM positionstyp pptt 
) tt
GROUP BY tt.id) ttt
UNION 
SELECT p1.id, null, concat(pt1.bau_nr_komplett," #"), 
    IFNULL(ROUND(sum(m1.menge * p1.preis_kostenanschlag),0),0) as summe_kostenanschlag,
    IFNULL(ROUND(sum(m1.menge * p1.preis_kostenanschlag * m1.baufortschritt/100 ),0),0) as summe_kostenanschlag_baufortschritt,
    IFNULL(ROUND(sum(m1.menge * p1.preis_vertragskosten ),0),0) as summe_vertragskosten,
    IFNULL(ROUND(sum(m1.menge * p1.preis_vertragskosten * m1.baufortschritt/100 ),0),0) as summe_vertragskosten_baufortschritt,
    IFNULL(ROUND(sum(m1.menge * p1.preis_gemittelte_angebotskosten ),0),0) as summe_gemittelteangebotskosten,
    IFNULL(ROUND(sum(m1.menge * p1.preis_gemittelte_angebotskosten * m1.baufortschritt/100 ),0),0) as summe_gemittelteangebotskosten_baufortschritt
FROM menge m1 JOIN projektposition p1 ON (m1.projektposition_id=p1.id) JOIN positionstyp pt1 ON (p1.positionstyp_id=pt1.id)
WHERE p1.projekt_id=projektID AND p1.positionstyp_id IS NOT NULL
GROUP BY p1.id
) tttt
ORDER BY tttt.bau_nr_komplett;
END

我很高兴它可以在menge中使用超过1百万个数据集,在projektposition中使用10000个,在positionstyp中使用500个数据集 在2.5秒^^ !!!