【问题标题】:Multiple Groupings with left join not working左连接的多个分组不起作用
【发布时间】:2015-08-09 18:09:24
【问题描述】:

我试图解决这个问题好几天,但没有成功。我希望你的专业知识:

我想要实现的分组,同样位于:http://imgur.com/q8qoAVQ

sqlfiddle 上提供的示例:http://sqlfiddle.com/#!9/e42e6/2

DDL 和示例数据

CREATE TABLE tx_management_domain_model_events (
    `uid` int(11) NOT NULL,
    `title` varchar(255),
    PRIMARY KEY(uid)
);

CREATE TABLE tx_management_domain_model_programm (
    `uid` int(11) NOT NULL,
    `jobtype` int(11) unsigned DEFAULT '0' NOT NULL,
    `reservation` int(11) DEFAULT '0' NOT NULL,
    `eventdate` date NULL,
    `event` int(11) DEFAULT '0' NOT NULL,
    PRIMARY KEY(uid)
);

CREATE TABLE tx_management_domain_model_reservations (
    `uid` int(11) NOT NULL,
    `event` int(11) default '0',
    `feuser` int(11) DEFAULT '0',
    `status` int(11) DEFAULT '0' NOT NULL,
    `ressource` int(11) DEFAULT '0',
    PRIMARY KEY(uid)
);

CREATE TABLE tx_management_domain_model_appointments (
    `uid` int(11) NOT NULL,
    `begin` int(11) DEFAULT '0' NOT NULL,
    `end` int(11) DEFAULT '0' NOT NULL,
    `event` int(11) unsigned DEFAULT '0' NOT NULL,
    PRIMARY KEY(uid)
);

CREATE TABLE tx_management_domain_model_additionalcosts (
    `uid` int(11) NOT NULL,
    `additionalcosttype` int(11) unsigned DEFAULT '0' NOT NULL,
    `event` int(11) DEFAULT '0' NOT NULL,
    `feuser` int(11) DEFAULT '0' NOT NULL,
    `reservation` int(11) DEFAULT '0' NOT NULL,
    PRIMARY KEY (uid)
);

CREATE TABLE tx_management_domain_model_referents (
    `uid` int(11) NOT NULL,
    `specialsallary` text NULL,
    `feuser` int(11) unsigned DEFAULT '0' NOT NULL,
    `event` int(11) unsigned DEFAULT '0' NOT NULL,  
    PRIMARY KEY(uid)
);

CREATE TABLE fe_users (
    `uid` int(11) NOT NULL,
    `fullname` varchar(255),
    PRIMARY KEY(uid)
);

# ---------------------- Fill with data --------------------
INSERT INTO tx_management_domain_model_events
    (`uid`, `title`)
VALUES
    (1660, 'Event-1'),
    (1632, 'Event-2');

INSERT INTO tx_management_domain_model_programm
    (`uid`, `jobtype`, `reservation`, `event`, `eventdate`)
VALUES
    (1149, 2, 11259, 1660, '2015-05-04'),
    (1154, 0, 11278, 1660, '2015-05-04'),
    (1534, 0, 11783, 1660, '2015-07-11');

INSERT INTO tx_management_domain_model_reservations
    (`uid`, `event`, `feuser`, `status`, `ressource`)
VALUES
    (11259, 1660, 116740, 1105, 19901),
    (11278, 1660, 116740, 1105, 19901),
    (11280, 1660, 117354, 1101, 19902),
    (11783, 1660, 116740, 1101, 19901),
    (11784, 1660, 116740, 1101, 100001);

INSERT INTO tx_management_domain_model_appointments
    (`uid`, `begin`, `end`, `event`)
VALUES
    (1104, 1430690400, 1432936800, 1660),
    (1123, 1436565600, 1436652000, 1660),
    (1127, 1436306400, 1436911200, 1632);

INSERT INTO tx_management_domain_model_additionalcosts
    (`uid`, `additionalcosttype`, `event`, `feuser`, `reservation`)
VALUES
    (1, 0, 1660, 11740, 11784);

INSERT INTO tx_management_domain_model_referents
    (`uid`, `specialsallary`, `feuser`, `event`)
VALUES
    (1885, '', 116740, 1660),
    (1935, '', 116740, 1632);

INSERT INTO fe_users
    (`uid`, `fullname`)
VALUES
    (116740, 'John Kohn');

SQL 查询

select
    group_concat(distinct tbl_events.uid) as Event,
    date_format(from_unixtime(tbl_appointments.`begin`),get_format(DATE, 'EUR')) AS 'appointmentBegin',
    date_format(from_unixtime(tbl_appointments.`end`),get_format(DATE, 'EUR')) AS 'appointmentEnd',
    group_concat(distinct tbl_reservations.ressource) as Ressource,
    group_concat(distinct tbl_programm.jobtype) as Jobtyp,
    group_concat(tbl_reservations.uid) AS Reservations,
    group_concat(distinct tbl_referents.specialsallary) AS Specialsallary
from 
    tx_management_domain_model_events tbl_events
    inner join tx_management_domain_model_reservations as tbl_reservations on tbl_reservations.event = tbl_events.uid
    inner join tx_management_domain_model_appointments as tbl_appointments on tbl_events.uid = tbl_appointments.event
    left join tx_management_domain_model_programm as tbl_programm on tbl_reservations.uid = tbl_programm.reservation and tbl_programm.eventdate between from_unixtime(tbl_appointments.`begin`) and from_unixtime(tbl_appointments.`end`)
    left join tx_management_domain_model_additionalcosts as tbl_additionalcosts on tbl_reservations.uid = tbl_additionalcosts.reservation
    inner join fe_users on tbl_reservations.feuser = fe_users.uid
    inner join tx_management_domain_model_referents as tbl_referents on tbl_reservations.feuser = tbl_referents.feuser
where tbl_reservations.feuser = 116740
    and tbl_reservations.ressource in (19901,19902,100001,100002)
    and tbl_referents.event = tbl_events.uid
    and tbl_programm.event = tbl_events.uid
group by
    tbl_events.uid,
    CASE WHEN (tbl_reservations.ressource in (19901,19902,100001,100002) AND ((tbl_referents.specialsallary IS NULL) OR (tbl_referents.specialsallary LIKE ''))) THEN tbl_reservations.ressource ELSE tbl_referents.specialsallary END,
    from_unixtime(tbl_appointments.`begin`),
    from_unixtime(tbl_appointments.`end`),
    tbl_programm.jobtype;

问题:没有显示 tx_management_domain_model_additionalcosts 中的记录。

预期:预订“11784”也应该在结果列“预订”中。

提示:如果我注释掉 tbl_programm 的每个 WHERE 条件,则会显示 tbl_additionalcosts 的记录。但为什么我必须删除这些条件?

有人知道我哪里出了问题吗?

【问题讨论】:

  • 您应该在问题中包含示例数据和所需的结果。 Stack Overflow 问题不应依赖于其他网站才有意义。
  • 这里应该包括什么?如您所见,数据太多
  • 如果数据太多,那么您并没有将问题归结为核心。将您的示例最小化为简单的东西。我们希望问题对未来的访问者也有用,如果他们和您有同样的问题,他们需要快速理解。所以试着概括你的问题
  • 抱歉,我无法处理您的命名政策
  • 但是,请注意 CASE WHEN (r.ressource in (19901,19902,100001,100002) 是多余的,因为 r.ressource 始终是这些代码之一......并且LEFT JOIN programm... WHERE programm... = INNER JOIN programm... WHERE programm

标签: mysql join group-by


【解决方案1】:

您在 where 子句中的一个条件是排除他的保留“11784”,见下文它是孤立的。

select
    tbl_reservations.uid
from 
    tx_management_domain_model_events tbl_events
    inner join tx_management_domain_model_reservations as tbl_reservations on tbl_reservations.event = tbl_events.uid
    inner join tx_management_domain_model_appointments as tbl_appointments on tbl_events.uid = tbl_appointments.event
    left join tx_management_domain_model_programm as tbl_programm on tbl_reservations.uid = tbl_programm.reservation and tbl_programm.eventdate between from_unixtime(tbl_appointments.`begin`) and from_unixtime(tbl_appointments.`end`)
    left join tx_management_domain_model_additionalcosts as tbl_additionalcosts on tbl_reservations.uid = tbl_additionalcosts.reservation
    inner join fe_users on tbl_reservations.feuser = fe_users.uid
    inner join tx_management_domain_model_referents as tbl_referents on tbl_reservations.feuser = tbl_referents.feuser
where tbl_reservations.feuser = 116740
    and tbl_reservations.ressource in (19901,19902,100001,100002)

    /* JOIN */
    and tbl_referents.event = tbl_events.uid

    /* JOIN & this condition excludes "11784"*/
    and tbl_programm.event = tbl_events.uid

order by
    tbl_reservations.uid

注意谓词和它之前的谓词都是 JOINING 不过滤 所以,我的建议是将这两个都移到 FROM 子句中

结果

| Event | appointmentBegin | appointmentEnd | Ressource | Jobtyp | Reservations | Specialsallary |
|-------|------------------|----------------|-----------|--------|--------------|----------------|
|  1660 |       03.05.2015 |     29.05.2015 |    100001 | (null) |        11784 |                |
|  1660 |       10.07.2015 |     11.07.2015 |    100001 | (null) |        11784 |                |
|  1660 |       03.05.2015 |     29.05.2015 |     19901 | (null) |        11783 |                |
|  1660 |       03.05.2015 |     29.05.2015 |     19901 |      0 |        11278 |                |
|  1660 |       03.05.2015 |     29.05.2015 |     19901 |      2 |        11259 |                |
|  1660 |       10.07.2015 |     11.07.2015 |     19901 | (null) |  11259,11278 |                |
|  1660 |       10.07.2015 |     11.07.2015 |     19901 |      0 |        11783 |                |

通过修改后的查询

select
    group_concat(distinct tbl_events.uid) as Event,
    date_format(from_unixtime(tbl_appointments.`begin`),get_format(DATE, 'EUR')) AS 'appointmentBegin',
    date_format(from_unixtime(tbl_appointments.`end`),get_format(DATE, 'EUR')) AS 'appointmentEnd',
    group_concat(distinct tbl_reservations.ressource) as Ressource,
    group_concat(distinct tbl_programm.jobtype) as Jobtyp,
    group_concat(tbl_reservations.uid) AS Reservations,
    group_concat(distinct tbl_referents.specialsallary) AS Specialsallary
from 
    tx_management_domain_model_events tbl_events
    inner join tx_management_domain_model_reservations as tbl_reservations on tbl_reservations.event = tbl_events.uid
    inner join tx_management_domain_model_appointments as tbl_appointments on tbl_events.uid = tbl_appointments.event
    left join tx_management_domain_model_programm as tbl_programm on tbl_reservations.uid = tbl_programm.reservation and tbl_programm.eventdate between from_unixtime(tbl_appointments.`begin`) and from_unixtime(tbl_appointments.`end`)
    and tbl_programm.event = tbl_events.uid

    left join tx_management_domain_model_additionalcosts as tbl_additionalcosts on tbl_reservations.uid = tbl_additionalcosts.reservation
    inner join fe_users on tbl_reservations.feuser = fe_users.uid
    inner join tx_management_domain_model_referents as tbl_referents on tbl_reservations.feuser = tbl_referents.feuser
    and tbl_referents.event = tbl_events.uid

where tbl_reservations.feuser = 116740
    and tbl_reservations.ressource in (19901,19902,100001,100002)
group by
    tbl_events.uid,
    CASE WHEN (tbl_reservations.ressource in (19901,19902,100001,100002) AND ((tbl_referents.specialsallary IS NULL) OR (tbl_referents.specialsallary LIKE ''))) THEN tbl_reservations.ressource ELSE tbl_referents.specialsallary END,
    from_unixtime(tbl_appointments.`begin`),
    from_unixtime(tbl_appointments.`end`),
    tbl_programm.jobtype;

注意:如果您在通过外连接连接的表的 where 子句中包含谓词,则可以很容易地覆盖该外连接的效果,因此它实际上变成了内连接。

【讨论】:

  • 感谢您的提示。这确实是问题所在。但是现在,正如您所看到的,我们遇到了一个不同的问题:我们为“额外成本”记录获得多条记录/行 - 事件的每个约会 -> 我想要实现的是:只有 1 条记录用于额外成本,因为它有没有约会。问题是:1)“additionalcosts”与约会相关,因为约会与事件相关,这也与额外成本相关 2)我们没有像“program->eventdate”那样的限制。因此,我们获得了所有额外费用的预约记录我们怎么能这样做?
  • “如你所见......”但我没有看到这一点。不要假设我们熟悉您的数据和要求(因为我们不熟悉)。我相信我已经回答了最初的问题,但听起来您现在有一个新问题。
  • 好的,也许我现在看到了更多您的意思,但我不太了解您的需求,无法立即提出解决方案。您可能需要更多的案例表达式。您可以从选择和分组子句中排除 appointmentBegin & AppointmentEnd 吗?
  • 不,我无法删除。我需要它们。
  • 如果你还想要更少的行,你必须对它们做一些事情
猜你喜欢
  • 2015-12-02
  • 2012-09-10
  • 2019-02-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多