2010-06-06 4 views
2

У меня есть две таблицы reports и holidays.Комплексный запрос в mysql

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  |   | 
    +----------+-----------+---------+------------+ 

Как я могу изменить приведенный выше запрос, чтобы получить желаемый результат (для конкретного пользователя (Гаутама в этом случае))?

EDIT

У меня также есть таблица dates(date date), который содержит все даты между 2009-01-01 до 2020-12-31

+1

У вас также есть третья таблица «даты». Теперь я, вероятно, могу угадать структуру и содержимое таблицы этой таблицы, но для полноты вы, вероятно, должны добавить ее в вопрос. –

+0

@mark: спасибо ..... отредактировал :) – Satish

ответ

2

Двигайте ИНЕКЕ внутри JOIN статей. Единственное, что я изменил это последняя пара строк:

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

+0

@Satish: Несмотря на то, что вы приняли мой ответ, я думаю, что мой оригинальный ответ не совсем сделал то, что вы хотели, поэтому я обновил его с исправлением. Если вы считаете, что обновление не так, я могу вернуться к ответу, который вы приняли. –

+0

@Mark Byers: отбросьте свой ответ, на самом деле я ошибался, принимая диапазон дат, поэтому я получил абсурдный результат, но ваш предыдущий ответ сработал. – Satish

1

ответ Марка будет работать отлично, но вы делаете что-то, что очень плохая практика - вы используете SQL для форматирования информации. Это плохо! Вы должны использовать его только для извлечения вашей информации, а затем отформатировать ее с помощью HTML или того, что вы вставляете в данные. Ваш выбор должен быть простым:

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

И отдельный для праздников, если вам это нужно:

SELECT * from holidays 

И затем использовать эту информацию, как вам нужно.

+0

Я не согласен - SQL будет масштабироваться намного лучше, чем код приложения по мере увеличения набора результатов. А во-вторых - вопрос о возвращении правильных результатов, а не форматировании. –

+0

Основная часть запроса в вопросе - форматирование - использование COALESCE для возврата пустого пространства вместо NULL и наличие отдельной таблицы дат, чтобы на каждую дату была строка. Даже если он масштабируется лучше, просто вытаскивая информацию, он позволяет изменить способ отображения информации на лицевой стороне, не загружая запросы. Вот почему это считается плохой практикой. – colinmarc

Смежные вопросы