在sql中查询涉及两个表的连接

时间:2010-06-05 05:47:26

标签: sql mysql

编辑2

我有两张表reportsholidays

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-04 |  
| 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-09';

我得到了以下输出

   +----------+-----------+---------+------------+  
   |  date    |  activity |  hours  |   holiday  |
   +----------+-----------+---------+------------+  
   |2009-01-04|   coding  |    1    |            |
   +----------+-----------+---------+------------+

但我期待这个

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

如何修改上述查询以获得所需的输出(针对特定用户(在本例中为gautam))?

3 个答案:

答案 0 :(得分:1)

更新2:以下是您的新问题的答案。请注意,您错误地使用了CASE语句 - 如果{1}}不为空,则COALESCE(reports.activity, 'Absent')将返回reports.activity,如果是'Absent',则返回dates

首先,您需要一个表CREATE TABLE dates (date date); ,其中包含您要检查的日期,如下所示:

date      
----------
2009-01-01
2009-01-02
2009-01-03
2009-01-04
2009-01-05
2009-01-06
2009-01-07
2009-01-08
2009-01-09
2009-01-10

然后立即手动填写:

SELECT dates.date AS date,
CASE WHEN holiday_name IS NULL THEN COALESCE(user_reports.activity, 'Absent')
 ELSE '' END AS activity,
CASE WHEN holiday_name IS NULL THEN COALESCE(user_reports.hours, 'Absent')
 ELSE '' END AS hours,
COALESCE(holidays.holiday_name, '') AS holiday_name
FROM dates
LEFT OUTER JOIN 
 (SELECT * FROM reports WHERE reports.username='guatam') AS user_reports
 ON dates.date = user_reports.report_date 
LEFT OUTER JOIN holidays ON dates.date = holidays.holiday_date
WHERE dates.date>='2009-01-01' and dates.date<='2009-01-09';

这可以在程序上创建,但这完全是另一个主题。

这是查询,使用左外连接和嵌套选择:

date        activity    hours       holiday_name
----------  ----------  ----------  ------------
2009-01-01  Absent      Absent                  
2009-01-02                          Diwali      
2009-01-03  Absent      Absent                  
2009-01-04  coding      1                       
2009-01-05                          Holi        
2009-01-06  Absent      Absent                  
2009-01-07  Absent      Absent                  
2009-01-08  Absent      Absent                  
2009-01-09  Absent      Absent       

返回:

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

但真正的问题是你正在做一些非常糟糕的做法 - 你正在使用SQL格式化你的信息。这很糟糕!您应该只使用它来检索您的信息,然后使用HTML或任何您将数据提取到的格式进行格式化。你的选择应该很简单:

SELECT * from holidays

如果你需要假期,可另外选一个:

{{1}}

然后根据需要使用该信息。

答案 1 :(得分:0)

我不确定你的意思:

  

用“On”填写缺少的日期......   离开“

您可以通过对填充了所需日期范围内日期列表的表格执行一对outer joins来完成请求的剩余部分。

答案 2 :(得分:0)

这是上面colinmarc答案的延伸,只是为了说明如何避免在假期中“缺席”。否则答案与他的答案大致相同。

SELECT
    d.adate AS `date`,
    CASE WHEN holiday_name IS NULL THEN coalesce(activity, 'Absent') 
    ELSE '' END AS activity,
    CASE WHEN holiday_name IS NULL THEN coalesce(hours, 'Absent') 
    ELSE '' END AS activity,
    coalesce(holiday_name, '')
FROM (
    SELECT holiday_date AS adate FROM holidays
    UNION
    SELECT report_date AS adate FROM reports
) d
LEFT JOIN reports r ON (d.adate = r.report_date)
LEFT JOIN holidays h ON (d.adate = h.holiday_date)
ORDER BY adate ASC