2010-06-06 8 views
2

J'ai deux tables reports et holidays.Requête complexe dans 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 donne

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

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

Quand je les suivantes requête

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

j'ai obtenu la sortie suivante

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

mais je m'y attendais ce

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

Comment puis-je modifier la requête ci-dessus pour obtenir la sortie désirée (pour un utilisateur particulier (Gautam dans ce cas))?

EDIT

J'ai aussi une table dates(date date) qui contient toutes les dates entre 2009-01-01-2020-12-31

+1

Vous avez également une troisième table 'dates'. Maintenant, je peux probablement deviner la structure de la table et le contenu de cette table, mais pour être complet, vous devriez probablement l'ajouter à la question. –

+0

@mark: merci ..... édité :) – Satish

Répondre

2

Déplacez vos clauses where dans les clauses JOIN. La seule chose que j'ai changé est les deux dernières lignes:

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' 

Vous avez accepté la réponse ci-dessus, mais d'autres tests ont montré que même si cela fonctionne pour vous, il ne fonctionne pas pour moi. Voici quelque chose qui fonctionne pour moi:

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

merci pour votre réponse. – Satish

+0

@Satish: Malgré que vous ayez accepté ma réponse, je pense que ma réponse originale n'a pas tout à fait fait ce que vous vouliez donc je l'ai mise à jour avec une correction. Si vous pensez que la mise à jour est erronée, je peux revenir à la réponse que vous avez acceptée. –

+0

@Mark Byers: Retournez votre réponse en fait je me trompais en prenant la plage de date, donc j'ai obtenu le résultat absurde, mais votre réponse précédente a fonctionné. – Satish

1

réponse de Mark fonctionnera très bien, mais vous faites quelque chose qui est très mauvaise pratique - vous utilisez SQL pour formater vos informations. C'est mauvais! Vous devriez l'utiliser uniquement pour récupérer vos informations, puis le mettre en forme avec du code HTML ou tout autre élément dans lequel vous extrayez les données. Votre sélection devrait être simple:

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

Et une autre pour les vacances, si vous en avez besoin:

SELECT * from holidays 

et ensuite utiliser cette information dont vous avez besoin.

+0

Je ne suis pas d'accord - SQL évoluera beaucoup mieux que le code de l'application lorsque le résultat sera plus grand. Et d'autre part - la question est de retourner des résultats corrects, pas de mise en forme. –

+0

La plupart de la requête dans la question est mise en forme - en utilisant COALESCE pour retourner l'espace vide au lieu de NULL, et ayant une table de dates distincte afin qu'il y ait une ligne pour chaque date. Même si elle évolue mieux, le simple fait de tirer l'information lui permet de changer la façon dont les informations sont affichées sur le frontal sans avoir à se soucier des requêtes. C'est pourquoi c'est considéré comme une mauvaise pratique. – colinmarc