2010-06-06 194 views
2

我有两个表reportsholidaysmysql中的复杂查询

reports(username varchar(30),activity varchar(30),hours int(3),report_date date)

holidays(holiday_name varchar(30), holiday_date date)

select * from reports

+----------+-----------+---------+------------+ 
| username | activity | hours | date  | 
+----------+-----------+---------+------------+ 
| prasoon | testing | 3 | 2009-01-01 | 
| prasoon | coding | 4 | 2009-01-03 | 
| gautam | coding | 1 | 2009-01-05 | 
| prasoon | coding | 4 | 2009-01-06 | 
| prasoon | coding | 4 | 2009-01-10 | 
| gautam | coding | 4 | 2009-01-10 | 
+----------+-----------+---------+------------+ 

select * from holidays

+--------------+---------------+ 
| holiday_name | holiday_date | 
+--------------+---------------+ 
| Diwali  | 2009-01-02 | 
| Holi   | 2009-01-05 | 
+--------------+---------------+ 

当我用下面的查询

SELECT dates.date AS date, 
    CASE 
    WHEN holiday_name IS NULL THEN COALESCE(reports.activity, 'Absent') 
    WHEN holiday_name IS NOT NULL and reports.activity IS NOT NULL THEN reports.activity 
    ELSE '' 
    END 
    AS activity, 
    CASE WHEN holiday_name IS NULL THEN COALESCE(reports.hours, 'Absent') 
    WHEN holiday_name IS NOT NULL and reports.hours IS NOT NULL THEN reports.hours 
    ELSE '' 
    END 
    AS hours, 
    CASE 
    WHEN holiday_name IS NULL THEN COALESCE(holidays.holiday_name, '') 
    ELSE holidays.holiday_name 
    END 
    AS holiday_name 
    FROM dates 
    LEFT OUTER JOIN reports ON dates.date = reports.date 
    LEFT OUTER JOIN holidays ON dates.date = holidays.holiday_date 
    where reports.username='gautam' and dates.date>='2009-01-01' and dates.date<='2009-01-10'; 

我得到了以下输出

+----------+-----------+---------+------------+ 
    | date | activity | hours | holiday | 
    +----------+-----------+---------+------------+ 
    |2009-01-05| coding | 1 | Holi  | 
    +----------+-----------+---------+------------+ 
    |2009-01-10| coding | 4 |   | 
    +----------+-----------+---------+------------+ 

,但我预计今年

+----------+-----------+---------+------------+ 
    | date | activity | hours | holiday | 
    +----------+-----------+---------+------------+ 
    |2009-01-01| Absent | Absent |   | 
    +----------+-----------+---------+------------+ 
    |2009-01-02|   |   | Diwali  | 
    +----------+-----------+---------+------------+ 
    |2009-01-03| Absent | Absent |   | 
    +----------+-----------+---------+------------+ 
    |2009-01-04| Absent | Absent |   | 
    +----------+-----------+---------+------------+ 
    |2009-01-05| Coding | 1  | Holi  | 
    +----------+-----------+---------+------------+ 
    |2009-01-06| Absent | Absent |   | 
    +----------+-----------+---------+------------+ 
    |2009-01-07| Absent | Absent |   | 
    +----------+-----------+---------+------------+ 
    |2009-01-08| Absent | Absent |   | 
    +----------+-----------+---------+------------+ 
    |2009-01-09| Absent | Absent |   | 
    +----------+-----------+---------+------------+ 
    |2009-01-10| Coding | 4  |   | 
    +----------+-----------+---------+------------+ 

如何修改上面的查询以获得所需的输出(用于特定用户(高塔姆在这种情况下))?

编辑

我也有一个表dates(date date)包含所有2009-01-01之间的日期2020-12-31

+1

你也有第三个表'日期'。现在我可以猜测这个表的表格结构和内容,但为了完整性,您可能应该将其添加到问题中。 – 2010-06-06 18:53:33

+0

@mark:谢谢.....编辑:) – Satish 2010-06-06 18:57:02

回答

2

移动JOIN子句中的WHERE子句。我唯一改变的是最后几行:

FROM dates 
LEFT JOIN reports ON dates.date = reports.date 
AND reports.username='gautam' 
LEFT JOIN holidays ON dates.date = holidays.holiday_date 
AND dates.date >= '2009-01-01' 
AND dates.date <= '2009-01-10' 

你同意这个答案的上方,但进一步的测试表明,虽然它为你的作品,它没有为我工作。下面是一些对我的作品:

FROM dates 
LEFT JOIN reports ON dates.date = reports.date 
AND reports.username='gautam' 
LEFT JOIN holidays ON dates.date = holidays.holiday_date 
WHERE dates.date >= '2009-01-01' 
AND dates.date <= '2009-01-10' 
+0

感谢您的回复。 – Satish 2010-06-06 19:25:18

+0

@Satish:尽管你已经接受了我的回答,但我认为我原来的回答并不完全符合你的要求,所以我通过更正来更新它。如果您认为更新是错误的,我可以回滚到您接受的答案。 – 2010-06-06 19:29:20

+0

@Mark Byers:回滚你的答案其实我错误地采取了日期的范围,所以我得到了荒谬的结果,但你以前的答案已经奏效。 – Satish 2010-06-06 19:46:02

1

马克的回答会是不错的,但你正在做的东西的做法很可怜 - 你使用SQL格式化您的信息。这不好!您应该只使用它来检索您的信息,然后使用HTML格式或任何将数据拉入的格式。你的选择应该是一个简单:

SELECT * FROM reports WHERE username='guatam' 
AND date>='2009-01-01' AND date<='2009-01-9' 

和一个单独的一个假期,如果你需要它:

SELECT * from holidays 

然后利用这些信息,因为你需要。

+0

我不同意 - 当结果集变大时,SQL将比应用程序代码更好地扩展。其次,问题是关于返回正确的结果,而不是格式。 – 2010-06-06 20:37:55

+0

问题中的大部分查询都是格式化的 - 使用COALESCE来返回空白空间而不是NULL,并且有一个单独的日期表,以便每个日期都有一行。即使它的规模更好,只需提取信息就可以改变前端显示信息的方式,而不会影响查询。这就是为什么它被认为是不好的做法。 – colinmarc 2010-06-06 20:47:07