【问题标题】:Aggregation with rollup and empty records also还包含汇总和空记录的聚合
【发布时间】:2015-08-01 17:54:58
【问题描述】:

大家好,我有 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);

一个“menge”绑定到一个“projektposition”,一个“projektposition”绑定到一个“positionstyp”。那么一个“positionstyp”可能有一个父“positionstyp”。

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

所以一个menge的价格是(menge.menge * menge.baufortschritt * projektposition.preis_vertragskosten)

在我的 SELECT 中,我想要所有带有汇总价格的“positionstyp”条目,以及下面没有“menge”/“projektposition”的“positionstyp”条目,因此没有价格,仅适用于特定的“projekt_id”

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

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

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,但当然没有总结递归位置typ_parents。位置类型表的递归性可以更容易地在bau_nr_komplett 字段中找到:位置类型是所有位置类型的子项,即 bau_nr_komplett 是子位置类型的开头sbau_nr_komplett`(不必是直接的孩子)。

有人有想法吗?

感谢和最好的问候, 托比亚斯

现在的结果是:

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  

想要的结果是:

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

-- 编辑 2: 我找到了一个不好的解决方案。不好意味着它适用于测试数据集。但是对于真正的数据库和 100.000 个数据集,它需要半个小时;D

SELECT pt.bau_nr_komplett, (
 SELECT 
  SUM(IF(m1.menge IS NULL,0,m1.menge*p1.preis_vertragskosten*m1.baufortschritt/100*(p1.projekt_id=1325)))
 FROM positionstyp pt1
 LEFT JOIN projektposition p1 ON ( p1.positionstyp_id = pt1.id ) 
 LEFT JOIN menge m1 ON ( m1.projektposition_id = p1.id ) 
 WHERE pt1.bau_nr_komplett LIKE CONCAT( pt.bau_nr_komplett,  "%" ) 
 ) as summe
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_id "DEFAULT NULL" !?!?!?!?
  • 想要的结果,在 html 中,对不起。 DEFAULT NULL 是一个复制粘贴错误
  • 复制粘贴错误?有趣!

标签: mysql aggregation


【解决方案1】:

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

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

我很高兴它可以处理超过 100 万个 menge 数据集、10000 个 projektposition 和 500 个 positiontyp 数据集 在 2.5 秒内 ^^ !!!

【讨论】:

    猜你喜欢
    • 2020-10-09
    • 1970-01-01
    • 1970-01-01
    • 2019-03-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-01
    • 1970-01-01
    相关资源
    最近更新 更多