我知道有几十个“选择第一行”的问题,但我有一个有趣的情况,我认为我不能用LIMIT修复。
我正在尝试显示在开始日期和结束日期之间可用的属性,连续可用N天。我很亲密。
我打算把这个问题分成几个部分,因为它很重要。
(SELECT c.id,c.property_id,c.start_date,c.end_date FROM property_calendar as c WHERE c.start_date <= '.$endQuote.' AND c.end_date >= '.$startQuote)
UNION
(SELECT l.id,l.property_id,l.start_date,l.end_date FROM lease as l WHERE l.start_date <= '.$endQuote.' AND l.end_date >= '.$startQuote.' AND l.status < 6)
ORDER BY start_date ASC
这个联盟将我们的两个日历一起打破,以便于比较。每个条目都有一个start_date和end_date。落在(包括开始和结束)之间的日期被视为不可用。
SELECT IFNULL(DATEDIFF( IFNULL(ct2.start_date, '2015-12-09'), ct1.end_date) - 1, 0) as open_days,
(DATEDIFF(ct1.start_date, '2015-12-01') - 1) as first_open,
IFNULL(DATEDIFF( LEAST(ct1.end_date, '2015-12-09'), GREATEST(ct1.start_date, '2015-12-01' ) ) + 1, 0) as blocked_days,
ct1.property_id as property_id
FROM ({blocked dates}) as ct1
LEFT JOIN ({blocked dates}) as ct2 ON ct2.property_id = ct1.property_id AND ct2.start_date > ct1.end_date
GROUP BY ct1.property_id,ct1.start_date
这将获取第1部分中的表,并将其连接到自身,允许我们将之前的阻止日期与下一个阻止日期进行比较。 open_days
是每个阻止日期之间的负空间。 blocked_days
只是在ct1
中阻止了多少天。造成问题的部分是first_open
。
此查询有效,除非第一个阻止日期发生在用户提供的开始日期之后。在这种情况下,我们错过了那些开放的前几天。因此,我的部分解决方案是添加first_open
,只是简单地计算DATEDIFF( ct1.start_date, {the given start date})
。
SELECT cj.property_id,
IFNULL(SUM(cj.blocked_days), 0) as total_blocked,
IFNULL(GREATEST(MAX(cj.open_days), MAX(cj.first_open)), 0) as consec_days_avail
FROM {the calculator} as cj
正如我所说,这就是我遇到问题的地方。选择MAX(cj.first_open)
显然对我不起作用。我没有唯一的ID可用,因为可用性是两个表的组合,其中ID可能会发生冲突。并且MySQL没有FIRST()
函数可供使用。但基本上我只关心连续几天最大的因素,因为我们不关心连续几天发生的地方,只是它们发生在用户的开始和结束日期之间。
那么有更好的方法来构建这个查询吗?我已经尝试探索方法,只让计算器中的第一行实际为DATEDIFF()
,其他所有都为0,但我使用IF(ct1.start_date = MIN(ct1.start_date), DATEDIFF(...), 0)
的问题是前两行的非0价值,我只想要第一个。而且我认为这与我如何加入自己的表格有关。
感谢任何帮助。感谢。
对于好奇的派对,这里的查询全部是一个整体。现在这正在按预期工作(据我所知)。现在我只是想知道是否有更好的方法,或者是否有任何提示。
SELECT p.* as id, IFNULL(cd.total_blocked, 0) as total_blocked, IFNULL(cd.consec_days_avail, 0) as consec_days_avail
FROM properties AS p
LEFT JOIN (
SELECT cj.property_id, IFNULL(SUM(cj.blocked_days), 0) as total_blocked, IFNULL(GREATEST(MAX(cj.open_days), MAX(cj.first_open)), 0) as consec_days_avail
FROM (
SELECT IFNULL(DATEDIFF( IFNULL(ct2.start_date2, {user_end_date}), ct1.end_date) - 1, 0) as open_days,IF( MIN(ct1.start_date) = ct1.start_date, DATEDIFF(ct1.start_date, {user_start_date}), 0) as first_open,IFNULL(DATEDIFF( LEAST(ct1.end_date, {user_end_date}), GREATEST(ct1.start_date, {user_start_date} ) ) + 1, 0) as blocked_days,ct1.property_id as property_id
FROM ((SELECT c.id,c.property_id,c.start_date,c.end_date FROM property_calendar as c WHERE c.start_date <= {user_end_date} AND c.end_date >= {user_start_date}) UNION (SELECT l.id,l.property_id,l.start_date,l.end_date FROM lease as l WHERE l.start_date <= {user_end_date} AND l.end_date >= {user_start_date} AND l.status < 6) ORDER BY start_date ASC) as ct1
LEFT JOIN ((SELECT c.id as id2,c.property_id as property_id2,c.start_date as start_date2,c.end_date as end_date2 FROM property_calendar as c WHERE c.start_date <= {user_end_date} AND c.end_date >= {user_start_date}) UNION (SELECT l.id,l.property_id,l.start_date,l.end_date FROM lease as l WHERE l.start_date <= {user_end_date} AND l.end_date >= {user_start_date} AND l.status < 6) ORDER BY start_date2 ASC) as ct2 ON ct2.property_id2 = ct1.property_id AND ct2.start_date2 > ct1.end_date
GROUP BY ct1.property_id,ct1.start_date) as cj
GROUP BY cj.property_id) as cd on cd.property_id = p.id
WHERE p.state = 1
GROUP BY p.id
HAVING total_blocked < DATEDIFF({user_end_date},{user_start_date}) + 1 AND ( consec_days_avail >= {user_days_avail} OR total_blocked = 0 )
ORDER BY p.id asc
答案 0 :(得分:0)
您好!
该问题的解决方案是 SQL函数,名为 MIN ,它的工作方式如下:
SELECT MIN(primary_key_column),the_other_columns FROM table_name;
正如您所看到的,在查询开始时(单词SELECT之后),您只需调用函数MIN并给出也是表的主键的列。
因为此函数找到最小值表的寄存器。我的意思是,如果所选列是INTEGER,它将在该列中找到具有最小数字的行
如果您正在使用 PHP ,则有一个函数可以将其称为 mysql_fetch_array ,对于此函数,您必须先使用另一个 PHP 进行操作。名为 mysql_query 的函数并像这样使用它
$myQuery = mysql_query("SELECT * FROM tablename",$conectionVariable)or die(mysql_error);
然后我们调用函数mysql_fetch_array并将其存储在如下变量中:
$myQueryArray = mysql_getch_array($myQuery)or die(mysql_error());
现在使用它你必须像普通数组一样调用它:
$myQueryArray['COLUMN_NAME']
并且它返回该列的值是第一行
嗯,那一切。