繁体   English   中英

左外部联接(MySQL)问题,此查询出了什么问题?

[英]Left Outer Join (MySQL) Issues, what's wrong with this query?

我在mySQL中有五个表,并且我正在处理学生费用模块,但是我在查询中遇到了一些问题,所以我无法获得适当的结果,所以请帮助我,如果您能对此查询提供一些反馈的话,我将不胜感激。

1.a)class_details表创建

CREATE TABLE `class_details` 
(`class_id_pk` int(11) NOT NULL AUTO_INCREMENT
,`class_name`varchar(200) NOT NULL
,`session` varchar(50) DEFAULT NULL
,`class_status` varchar(50) DEFAULT NULL
,PRIMARY KEY (`class_id_pk`)
,UNIQUE KEY `UNIQUE` (`class_name`,`session`)) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;

1.b)class_details插入

insert  into `class_details`
(`class_id_pk`,`class_name`,`session`,`class_status`) 
VALUES 
(1,'1st','2016-2017',NULL)
,(2,'2nd','2016-2017',NULL)
,(3,'3rd','2016-2017',NULL);

2.a)feedetails表创建

CREATE TABLE `feedetails` 
(`section_id_fk` int(50) NOT NULL
,`fees` varchar(30) DEFAULT NULL
,PRIMARY KEY (`section_id_fk`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;

2.b)eta插

insert  into `feedetails`(`section_id_fk`,`fees`) 
values 
(1,'1000')
,(2,'2000')
,(3,'3000')
,(4,'4000')
,(5,'5000')
,(6,'6000');

3.a)section_details创建

CREATE TABLE `section_details` 
(`section_id_pk` int(11) NOT NULL AUTO_INCREMENT
,`class_id_fk` int(11) NOT NULL
,`section_name` varchar(50) NOT NULL
,`section_status` varchar(50) DEFAULT NULL
,PRIMARY KEY (`section_id_pk`,`class_id_fk`,`section_name`)
,UNIQUE KEY `UNIQUE` (`class_id_fk`,`section_name`)
,CONSTRAINT `FK_section_details` FOREIGN KEY (`class_id_fk`) REFERENCES `class_details` (`class_id_pk`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=latin1;

3.b)section_details插入

insert  into `section_details` (`section_id_pk`,`class_id_fk`,`section_name`,`section_status`) 
values 
(1,1,'A',NULL)
,(2,2,'A',NULL)
,(3,3,'A',NULL);

4.a)学生费

CREATE TABLE `student_fee` 
( `sr_no` int(200) NOT NULL AUTO_INCREMENT
,`scholar_no`int(50) NOT NULL
,`paid_amount` int(200) DEFAULT NULL
,`due_amount` int(200) DEFAULT NULL
,`fee_date` date DEFAULT NULL
,`section_id_fk` int(50) DEFAULT NULL
,PRIMARY KEY (`sr_no`)
,KEY `FK_student_fee`(`section_id_fk`)
,CONSTRAINT `FK_student_fee` FOREIGN KEY (`section_id_fk`) REFERENCES `section_details` (`section_id_pk`) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=latin1;

4.b)学生费插入

insert  into student_fee` (`sr_no`,`scholar_no`,`paid_amount`,`due_amount`,`fee_date`,`section_id_fk`) 
values 
(3,5,800,200,'2016-06-16',1)
,(4,29,1000,0,'2016-06-16',1)
,(5,5,200,0,'2016-06-16',1);

5.a)student_details创建

CREATE TABLE `student_details` 
(`scholar_no` int(30) NOT NULL
,`fname` varchar(30) DEFAULT NULL
,`lname` varchar(30) DEFAULT NULL
,`stu_class` varchar(30) DEFAULT NULL
,`rte` varchar(30) DEFAULT NULL
,`active` varbinary(10) DEFAULT NULL
,PRIMARY KEY (`scholar_no`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;

5.b)student_details插入

insert  into `student_details` (`scholar_no`,`fname`,`lname`,`stu_class`,`rte`,`active`) 
values 
(5,'KP','PK','1','N','y')
,(29,'Abc','Xyz','1','N','y');

上面我提到了用于此查询的所有表详细信息。 第一次进入student_details表stu_class = 1,费用将为1000。当我在student_fee中插入一些值并使用我的查询时,结果是正确的,但是当我在student_fee中向另一位学生插入一些金额时,查询中添加了已支付的金额对于不正确的同一个学生,我想显示那些实际插入的学生的插入费用。

SELECT 
student_details.scholar_no
,student_details.fname
,student_details.lname
,student_details.stu_class
,feedetails.fees
,class_name
,section_name
,IF(sssf.paid_amount IS NULL,0,sssf.paid_amount) AS paid_amount 
FROM 
    (student_details 
    LEFT OUTER JOIN feedetails 
        ON student_details.stu_class = feedetails.section_id_fk
    ) 
LEFT OUTER JOIN 
    (SELECT 
    scholar
    , SUM(pa) AS paid_amount
    , SUM(pva) AS prev_paid_amount
    ,SUM(da) AS due_amount
    , SUM(dva) AS prev_due_amount
    ,section_id_fk
    ,fee_date
    ,stu_class 
    FROM 
        (SELECT 
        scholar
        ,CASE WHEN section_id_fk = stu_class THEN paid_amount ELSE 0 END AS pa
        ,CASE WHEN section_id_fk != stu_class THEN paid_amount ELSE 0 END AS pva
        ,CASE WHEN section_id_fk = stu_class THEN due_amount ELSE 0 END AS da
        ,CASE WHEN section_id_fk != stu_class THEN due_amount ELSE 0 END AS dva
        ,due_amount
        ,paid_amount
        ,section_id_fk
        ,fee_date
        ,stu_class 
        FROM 
            (SELECT 
            scholar
            ,due_amount
            ,SUM(paid_amount) AS paid_amount
            ,section_id_fk
            ,fee_date 
            FROM 
                (SELECT 
                student_fee.due_amount AS due_amount
                ,student_fee.paid_amount AS paid_amount
                ,student_fee.scholar_no AS scholar
                ,section_id_fk
                ,fee_date 
                FROM student_fee 
                ORDER BY STR_TO_DATE(fee_date,'%Y-%m-%d')DESC
                ) AS kkk 
            GROUP BY kkk.scholar,section_id_fk ORDER BY scholar
        ) AS k 
        LEFT OUTER JOIN student_details sd 
            ON k.scholar = sd.scholar_no
    ) AS lk
) AS sssf 
ON student_details.scholar_no = sssf.scholar 
LEFT OUTER JOIN 
    (SELECT * 
    FROM section_details AS sd 
    LEFT OUTER JOIN class_details cd 
        ON sd.class_id_fk = cd.class_id_pk
    ) AS sc 
ON student_details.stu_class = sc.section_id_pk 
WHERE student_details.active = 'y' AND rte = 'N'

复杂的查询。 和不幸的是。

首先,您可以从子查询中删除所有ORDER BY子句。 子查询仅返回无序集,因此子查询是否包含ORDER BY子句均无效(除了可能给DBMS带来不必要的工作之外)。

最里面的子查询(kkk)没有WHERE子句,也没有GROUP BY子句,因此您也可以直接从student_fee选择。

接下来的子查询(KK)的团体scholarsection_id_fk ,但你选择due_amountfee_date没有任何聚集。 这为您提供了任意选择的值。 那不应该是sum(due_amount)max(due_amount)之类的吗?

然后,在sssf子查询中,没有GROUP BY子句。 这样就给了您一个结果行。 但是,您选择了未fee_date scholarsection_id_fkfee_datestu_class ,因此再次获得了任意选择的值,例如,所有学者之一。

检查所有聚合。 设置ONLY_FULL_GROUP_BY模式可能有助于避免错误。

检查下面的SQL,我有一个快速修复。 如果不能解决,请再多解释一下您的问题。

SELECT 
student_details.scholar_no
,student_details.fname
,student_details.lname
,student_details.stu_class
,feedetails.fees
,class_name
,section_name
,IF(sssf.paid_amount IS NULL,0,sssf.paid_amount) AS paid_amount 
FROM 
    (student_details 
    LEFT OUTER JOIN feedetails 
        ON student_details.stu_class = feedetails.section_id_fk
    ) 
LEFT OUTER JOIN 
    (SELECT 
    scholar
    , SUM(pa) AS paid_amount
    , SUM(pva) AS prev_paid_amount
    ,SUM(da) AS due_amount
    , SUM(dva) AS prev_due_amount
    ,section_id_fk
    ,fee_date
    ,stu_class 
    FROM 
        (SELECT 
        scholar
        ,CASE WHEN section_id_fk = stu_class THEN paid_amount ELSE 0 END AS pa
        ,CASE WHEN section_id_fk != stu_class THEN paid_amount ELSE 0 END AS pva
        ,CASE WHEN section_id_fk = stu_class THEN due_amount ELSE 0 END AS da
        ,CASE WHEN section_id_fk != stu_class THEN due_amount ELSE 0 END AS dva
        ,due_amount
        ,paid_amount
        ,section_id_fk
        ,fee_date
        ,stu_class 
        FROM 
            (SELECT 
            scholar
            ,due_amount
            ,SUM(paid_amount) AS paid_amount
            ,section_id_fk
            ,fee_date 
            FROM 
                (SELECT 
                student_fee.due_amount AS due_amount
                ,student_fee.paid_amount AS paid_amount
                ,student_fee.scholar_no AS scholar
                ,section_id_fk
                ,fee_date 
                FROM student_fee 
                ORDER BY STR_TO_DATE(fee_date,'%Y-%m-%d')DESC
                ) AS kkk 
            GROUP BY kkk.scholar,section_id_fk ORDER BY scholar
        ) AS k 
        LEFT OUTER JOIN student_details sd 
            ON k.scholar = sd.scholar_no
    ) AS lk
    group by scholar
) AS sssf 
ON student_details.scholar_no = sssf.scholar 
LEFT OUTER JOIN 
    (SELECT * 
    FROM section_details AS sd 
    LEFT OUTER JOIN class_details cd 
        ON sd.class_id_fk = cd.class_id_pk
    ) AS sc 
ON student_details.stu_class = sc.section_id_pk 
WHERE student_details.active = 'y' AND rte = 'N'

尝试这个

SELECT 
student_details.scholar_no
,student_details.fname
,student_details.lname
,student_details.stu_class
,feedetails.fees
,class_name
,section_name
,IF(sssf.paid_amount IS NULL,0,sssf.paid_amount) AS paid_amount 
FROM 
    (student_details 
    LEFT OUTER JOIN feedetails 
        ON student_details.stu_class = feedetails.section_id_fk
    ) 
LEFT OUTER JOIN 
    (SELECT 
    scholar
    ,pa AS paid_amount
    ,pva AS prev_paid_amount
    ,da AS due_amount
    ,dva AS prev_due_amount
    ,section_id_fk
    ,fee_date
    ,stu_class 
    FROM 
        (SELECT 
        scholar
        ,CASE WHEN section_id_fk = stu_class THEN paid_amount ELSE 0 END AS pa
        ,CASE WHEN section_id_fk != stu_class THEN paid_amount ELSE 0 END AS pva
        ,CASE WHEN section_id_fk = stu_class THEN due_amount ELSE 0 END AS da
        ,CASE WHEN section_id_fk != stu_class THEN due_amount ELSE 0 END AS dva
        ,due_amount
        ,paid_amount
        ,section_id_fk
        ,fee_date
        ,stu_class 
        FROM 
            (SELECT 
            scholar
            ,due_amount
            ,paid_amount AS paid_amount
            ,section_id_fk
            ,fee_date 
            FROM 
                (SELECT 
    student_fee.due_amount AS due_amount,SUM(student_fee.paid_amount) AS paid_amount,student_fee.scholar_no AS scholar,section_id_fk,fee_date 
    FROM student_fee  GROUP BY scholar 
                ORDER BY STR_TO_DATE(fee_date,'%Y-%m-%d')DESC
                ) AS kkk 
             ORDER BY scholar
        ) AS k 
        LEFT OUTER JOIN student_details sd 
            ON k.scholar = sd.scholar_no
    ) AS lk
) AS sssf 
ON student_details.scholar_no = sssf.scholar 
LEFT OUTER JOIN 
    (SELECT * 
    FROM section_details AS sd 
    LEFT OUTER JOIN class_details cd 
        ON sd.class_id_fk = cd.class_id_pk
    ) AS sc 
ON student_details.stu_class = sc.section_id_pk 
WHERE student_details.active = 'y' AND rte = 'N'

我看过您的查询,您犯了一些错误,在查询中在AS lk之后使用GROUP BY scholar AS lk或在查询中查找AS lk并替换AS lk GROUP BY scholar ...!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM