从中获取数据以及到目前为止获取所有匹配结果

时间:2015-10-20 16:43:04

标签: postgresql

大家好我必须从中获取数据,到目前为止,我尝试使用between子句无法检索我需要的数据。这就是我需要的。 我有一个名为hall_info的表,其结构如下 hall_info

id | hall_name  |address  |contact_no
 1 |  abc       | India   |XXXX-XXXX-XX
 2 |  xyz       | India   |XXXX-XXXX-XX

现在我还有一个表是事件,其中包含有关何时以及在哪个日期预订的大厅的数据,结构如下。

id |hall_info_id |event_date(booked_date)| event_name
 1 |  2          |       2015-10-25      |    Marriage
 2 |  1          |       2015-10-28      |    Marriage
 3 |  2          |       2015-10-26      |    Marriage 

所以我现在需要的是我想在所选日期显示预订的hall_names,假设用户选择2015-10-23到2015-10-30所以我想列出所有大厅在选定日期未预订。在上面的例子中,hall_info_id 1和2 ids的大厅在给定范围内预订但我仍然想要显示它们,因为它们在23,24,27和29日期间是免费的。

在第二种情况下假设用户选择2015-10-25和2015-10-26的日期,那么在日期25和26上只预订了hall_info_id 2,所以在这种情况下我想只显示hall_info_id 1作为hall_info_id 2是预订。

我尝试使用内部查询和between子句但我没有得到所需的结果只是我只给了选定的字段我有更多的表加入所以我不能粘贴我的查询请帮助这个。提前感谢所有正在尝试的人。

3 个答案:

答案 0 :(得分:2)

Yasen Zhelev代码中的一些变化:

SELECT * FROM hall_info 
WHERE id not IN (
SELECT hall_info_id FROM events 
WHERE event_date >= '2015-10-23' AND event_date <= '2015-10-30'
GROUP BY hall_info_id
HAVING COUNT(DISTINCT event_date) > DATE_PART('day', '2015-10-30'::timestamp - '2015-10-23'::timestamp))

答案 1 :(得分:1)

我还没有尝试过,但是如何检查每个大厅的预订数量是否少于所选时段的实际天数。

SELECT * FROM hall_info WHERE id NOT IN
(SELECT hall_info_id FROM events
    WHERE event_date >= '2015-10-23' AND event_date <= '2015-10-30'
    GROUP BY hall_info_id
    HAVING COUNT(id) < DATEDIFF(day, '2015-10-30', '2015-10-23')
);

只有每个大厅每天预订一次才能使用。

答案 2 :(得分:0)

要获取返回大厅的“可用日期”,您的查询需要所有可能日期的行来源。例如,如果您有一个填充了可能日期值的日历表,例如

 CREATE TABLE cal (dt DATE NOT NULL PRIMARY KEY) Engine=InnoDB
 ; 
 INSERT INTO cal (dt) VALUES ('2015-10-23')
 ,('2015-10-24'),('2015-10-25'),('2015-10-26'),('2015-10-27')
 ,('2015-10-28'),('2015-10-29'),('2015-10-30'),('2015-10-31')
 ;

您可以使用在日历表和hall_info之间执行交叉连接的查询...来获取每个日期的每个大厅......以及反连接模式以消除已经预订的行。

反连接模式是一个外连接,在WHERE子句中有一个限制,用于消除匹配的行。

例如:

 SELECT cal.dt, h.id, h.hall_name, h.address
   FROM cal cal
  CROSS
   JOIN hall_info h
   LEFT
   JOIN events e
     ON e.hall_id = h.id
    AND e.event_date = cal.dt
  WHERE e.id IS NULL
    AND cal.dt >= '2015-10-23'
    AND cal.dt <= '2015-10-30'

cal和hall_info之间的交叉连接获取所有日期的所有大厅(在WHERE子句中限制为指定的日期范围。)

事件外部联接在事件表中查找匹配的行(在hall_id和event_date上匹配。技巧是WHERE子句e.id IS NULL中的谓词(条件)。抛出任何匹配的行,只留下没有匹配的行。

此类问题类似于其他“稀疏数据”问题。例如如果没有具有该商店和日期的行,您如何在给定日期返回给定商店的销售总额为零...

在您的情况下,查询需要具有可用日期值的行的源。这不一定是名为calendar的表。 (其他数据库使我们能够动态生成行源;有一天,MySQL可能具有类似的功能。)

如果你希望行源在MySQL中是动态的,那么一种方法是创建一个临时表,并用日期填充它,运行引用临时表的查询,然后删除临时表。

另一种方法是使用内联视图返回行...

 SELECT cal.dt, h.id, h.hall_name, h.address
   FROM ( 
          SELECT '2015-10-23'+INTERVAL 0 DAY AS dt
          UNION ALL SELECT '2015-10-24'
          UNION ALL SELECT '2015-10-25'
          UNION ALL SELECT '2015-10-26'
          UNION ALL SELECT '2015-10-27'
          UNION ALL SELECT '2015-10-28'
          UNION ALL SELECT '2015-10-29'
          UNION ALL SELECT '2015-10-30'
        ) cal
  CROSS
   JOIN hall_info h
   LEFT
   JOIN events e
     ON e.hall_id = h.id
    AND e.event_date = c.dt
  WHERE e.id IS NULL

关注:当这个问题最初发布时,它被标记为 mysql 。上面例子中的SQL是针对MySQL的。

在编写查询以返回指定结果方面,PostgreSQL中的一般问题仍然相同。一般问题是“稀疏数据”。

对于“缺失”的日期值,SQL查询需要行源,但规范不提供这些日期值的任何来源。

上面的答案讨论了MySQL中几种可能的行源:1)表,2)临时表,3)内联视图。

答案还提到一些数据库(不是MySQL)提供了可用作行源的其他机制。

例如,PostgreSQL提供了一个漂亮的 generate_series 函数(参考:http://www.postgresql.org/docs/9.1/static/functions-srf.html

应该可以使用generate_series函数作为行源,提供一组行,其中包含查询生成指定结果所需的日期值。

这个答案演示了解决“稀疏数据”问题的方法。

如果规范只返回大厅列表,而不是它们可用的日期,则可以轻松修改上述查询以从SELECT列表中删除日期表达式,并添加GROUP BY子句以折叠行进入一个独特的大厅列表。