我正在使用MariaDB-10.2.6。
目前架构如下:
CREATE TABLE `daily_report` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`date` date DEFAULT NULL,
`user_id` varchar(255) NOT NULL,
CONSTRAINT `daily_report_user_id_fk` FOREIGN KEY (`user_id`) REFERENCES `user`
(`id`) ON DELETE SET NULL ON UPDATE CASCADE
)
CREATE TABLE `user` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`shall_create_every_day` tinyint(1) NOT NULL
)
CREATE TABLE `calendar` (
`datefield` date
)
规则:
shall_create_every_day
设置为1
的用户每天都会创建一个daily_report
。calendar
,其中包含从2000-01-01
到2020-12-31
的每个日期(因为在MySQL / MariaDB中没有generate_series)我尝试了以下查询:
select daily_report.id, daily_report.date, user.id, calendar.datefield
from calendar
left join daily_report on daily_report.date=calendar.datefield
right join user on daily_report.user_id=user.id and user.shall_create_every_day=1
where calendar.datefield='2017-08-02'
我正在尝试使用日期范围,但出于测试目的,我将where
语句限制为仅限一天。
它将返回shall_create_every_day
的所有未在“2017-08-12”创建任何daily_report
的用户。但是我当天只得到了创建报告的组合。
有什么我误解左/右连接为不匹配的行返回空值?
答案 0 :(得分:1)
MariaDB中提供了Generate系列。见here。它就像
SELECT '2000-01-01' + INTERVAL seq
FROM seq_0_241
您可以JOIN
这样做,而无需实际实现表格。
请不要混用LEFT JOIN
和RIGHT JOIN
。这或者是问题的原因,或者我的头脑太忙于了解它。请记住,它可能被解释为
FROM a LEFT JOIN (b RIGHT JOIN c)
这可能不是你想要的。在任何情况下,都允许使用括号(并在混合LEFT
和RIGHT
时鼓励使用括号。)
答案 1 :(得分:0)
你以一种有点复杂的方式表达了你的疑问。我想通过将user
表连接到第二个表来表达这一点,该表包含每个用户每天报告的条目。没有写入的用户的标志是,给定的用户记录与第二个表中的任何内容都不匹配。
select
u.id
from user u
left join
(
select
c.datefield,
dr.me_id
from calendar c
left join daily_report dr
on dr.date = c.datefield
where c.datefield = '2017-08-02'
) cal
on cal.me_id = u.id and
u.shall_create_every_day = 1
where
cal.me_id is null;
答案 2 :(得分:0)
永远不要组合左右连接;这只是令人困惑。 (好吧,我们大多数人从来没有使用过正确的连接,因为它们更难以阅读然后离开连接。)
您的查询是这样做的:
首先,您应该问问自己:我是否需要外部联接?关于用户和日历,你没有。实际上你想要的日历是检查“2017-08-02”的条目是否存在。至于用户表:这也仅仅是标准;您想要某些用户的所有报告和特定日期。
因此,请从报告表中进行选择,并在其WHERE
子句中包含其所属的条件。
select id, date, user_id
from daily_report
where user_id in (select id from user where shall_create_every_day = 1)
and date = (select datefield from calendar where datefield = '20170802');
要显示日期和用户及其报告(包括缺少报告),您需要交叉加入日历和用户,然后加入报告:
select r.id, c.datefield, u.id as user_id
from (select id from user where shall_create_every_day = 1) u
cross join (select datefield from calendar where datefield = '20170802') c
left join daily_report r on r.user_id = u.id and r.date = c.datefield;
答案 3 :(得分:0)
可以这样做。
daily_report.user_id
P.S。可能表结构中存在错误。 int
应为varchar
而不是 <!DOCTYPE html>
<html>
<head>
<script src="jquery.js"></script>
<script>
$(document).ready(function(){
$('#a1').keyup(calculate);
$('#a2').keyup(calculate);
$('#a3').keyup(calculate);
});
function calculate(e) {
if ($('input.checkbox_check').is(':checked')) {
$('#a4').val(($('#a1').val() * $('#a2').val())*0.6);
$('#a3').val($('#a1').val() * $('#a2').val());
} else {
$('#a3').val($('#a1').val() * $('#a2').val());
$('#a4').val($('#a3').val() * 0.5);
}}
</script>
</head>
<body>
<div>Lengde <input id="a1" type="text" value="0" /></div>
<div>Bredde <input id="a2" type="text" value="0" /></div>
<div><input type="checkbox" name="checkbox" class="checkbox_check"></div>
<div>Antall kvm <input id="a3" type="text" value="0" /></div>
<div>Pris <input id="a4" type="text" value="0" /></div>
</body>
</html>
。