2010-09-18 20 views
0

J'ai du mal à faire fonctionner ma requête. Fondamentalement, ce qu'il devrait faire, c'est seulement des postes vacants qui n'ont pas été pourvus. Par exemple, un poste vacant peut avoir une limite préétablie de 5. Pour cela, il doit avoir un mélange de 5 réservations actives ou en attente ou simplement 5 réservations actives ou 5 en attente.Sql - lutter contre le nombre/avoir une requête basée sur plusieurs jointures

Une réservation en attente devient active lorsqu'un client l'accepte.

Il peut aider en fournissant un schéma de base de mon mise en place: -

**tbl.vacancies:** 
vacancy_id 
job_category_id 
business_unit_id 
start_date 
publication_date 
end_date 
limit - how many bookings it will accept 

**tbl.bookings** 
booking_id 
candidate_id 
vacancy_id 
booking_status_id 
user_id 
date 

**btl.booking_status** 
id 
user_id 
booking_status_type_id 
date 

**tbl.booking_status_type** 
id (1,2,3,4) 
name (pending, active, rejected, revoked) 

Ma requête fonctionne bien lors de l'affichage tous les postes que je crée une jointure entre le job_category, business_unit, candidat, booking_status et booking_status_type les tables. Mais j'ai une exigence où j'ai besoin d'afficher des données filtrées basées sur si un poste vacant a été rempli, c'est-à-dire qu'il a moins de réservations actives/en attente que la limite d'offres d'emploi ou qu'il a été complet.

La requête Je suis actuellement à l'aide est:

SELECT v.*, j.job_category_name, bu.business_unit_name 
FROM vacancy v 
INNER JOIN job_category j ON j.job_category_id = v.job_category_id 
INNER JOIN business_unit bu ON bu.business_unit_id = v.business_unit_id 
INNER JOIN booking b ON b.vacancy_id = v.vacancy_id 
INNER JOIN booking_status bs ON bs.id = b.booking_status_id 
WHERE 
    v.vacancy_status <> 'revoked' AND 
    v.vacancy_reference <> 'auto-generated booking' AND 
    v.business_unit_id IN (series of primary keys) AND 
(bs.booking_status_type_id = 1 OR bs.booking_status_type_id = 2) 
GROUP BY v.vacancy_id 
HAVING v.vacancy_limit > count(b.booking_id) 
ORDER BY v.vacancy_id DESC 

Le problème se produit lorsque j'annule une réservation (booking_status_type_id 4). Il semble gâcher les résultats ou n'en ramasser aucun.

Un petit scénario d'un changement d'état sur une réservation pourrait être: -

  1. utilisateur crée la réservation (état d'attente)
  2. client accepte (état actif)
  3. client décide alors de révoquer (Révoquer état)

Cela se traduira par des entrées comme ceci: -

Vacancy ID = 100; 
Booking ID = 10; 
Booking Status entries:- 

Booking_id Booking_status_type_id 
--------------------------------------- 
10   1 
10   2 
10   4 

Donc, en théorie, cette réservation ne devrait pas apparaître dans les résultats car la position a été supprimée et redevient disponible.

Cela entraînera 3 entrées dans la table booking_status_type pour les changements de statut sur la réservation.

Je ne suis pas sûr pourquoi ma requête ne fonctionne pas ou si elle est correctement construite. À titre d'exigence de base, lorsque l'utilisateur choisit de sélectionner si une réservation n'a pas été remplie, il ne doit afficher que des offres d'emploi dont la somme des réservations ne dépasse pas la limite de réservation.

De même, lors de la sélection pour filtrer sur les postes vacants remplis, il ne doit afficher que les postes vacants où la limite a été atteinte.

Edit # 1

D'accord, je l'ai essayé la mise en œuvre de la solution proposée, mais ne peut le faire fonctionner:

SELECT v.*, j.job_category_name, bu.business_unit_name 
FROM vacancy v 
INNER JOIN job_category j ON j.job_category_id = v.job_category_id 
INNER JOIN business_unit bu ON bu.business_unit_id = v.business_unit_id 
INNER JOIN booking b ON b.vacancy_id = v.vacancy_id 
INNER JOIN 
(SELECT booking_id AS bk_id, max(booking_status_type_id) AS bStatus 
FROM booking_status 
GROUP BY bk_id 
HAVING bStatus < 3) as filter ON filter.bk_id = b.booking_id 
WHERE 
    v.status <> 'revoked' AND 
    v.reference <> 'auto-generated booking' AND 
    v.business_unit_id IN (1, 2) 
GROUP BY v.vacancy_id 
HAVING v.limit > count(b.booking_id) 
ORDER BY v.vacancy_id DESC 

Je reçois l'erreur suivante:

1064 - You have an error in your SQL syntax. Check the manual that

corresponds to your MySQL server version for the right syntax to use near 'SELECT booking_id AS bk_id , max(booking_status_type_id) AS b

La version de MySQL est 4.0

+0

La requête semble bonne, mais sans les données, il est difficile de dire ce qui ne va pas. Essayez de simplifier le problème. Par exemple, supprimez ces tables de la jointure dont vous n'avez pas réellement besoin (business_unit, job_category). Ma conjecture est après que vous pouvez résoudre le problème vous-mêmes. –

Répondre

0

Vous comptiez les réservations qui ont le statut de 1 ou 2, mais je pense que vous devriez les réservations qui comptiez n'ont pas le statut de 3 ou 4 à la place - à savoir éliminer les réservations rejetées ou révoquées.

En fait, je vois maintenant que vous ne sélectionnez qu'un statut de réservation en utilisant la jointure de la table des réservations. Je soupçonne les données alors. Etes-vous sûr que l'état de réservation mentionné par l'identifiant dans booking_status_id est le dernier?

Après avoir poussé autour de cela, je voudrais vérifier les éléments suivants:

  1. Y at-il des statuts de réservation multiples avec le même identifiant?
  2. Le statut de réservation lié est-il le dernier?
  3. Êtes-vous sûr de vous joindre sur le statut id, pas le réservation id?

À part cela, je ne peux pas le voir.

+0

ceci est ce que je voulais dire :) – keshav84

+0

OK, mais je ne pense pas que votre solution résout ce problème. – nickd

+0

vrai !!! Je pensais que la jointure était entre booking_id, mais est-ce pas le problème il doit y avoir une condition de jointure sur booking_id qui manque – keshav84

0

le problème est que vous avez ignoré le fait que l'état de réservation pourrait avoir plusieurs entires pour le même numéro de réservation, et donc vous devez d'abord filtrer les bookingids valides comme ci-dessous

select booking_id as bk_id, max(Booking_status_type_id) status 
from booking_status 
group by booking_id 
having status < 3 

cette La requête ne vous renvoie que les ID de réservation en attente ou actifs. Vous pouvez ensuite filtrer les offres d'emploi en appliquant toutes les jointures que vous avez appliquées dans la requête que vous avez mentionnée. j'ai à peu près modifié votre requête pour le faire, vérifier si cela fonctionne

SELECT v.*, j.job_category_name, bu.business_unit_name 
FROM vacancy v 
INNER JOIN job_category j ON j.job_category_id = v.job_category_id 
INNER JOIN business_unit bu ON bu.business_unit_id = v.business_unit_id 
INNER JOIN booking b ON b.vacancy_id = v.vacancy_id 
INNER JOIN 
(select booking_id as bk_id, max(Booking_status_type_id) status 
from booking_status 
group by booking_id 
having status < 3) as filter ON filter.bk_id = b.booking_id 
WHERE 
    v.vacancy_status <> 'revoked' AND 
    v.vacancy_reference <> 'auto-generated booking' AND 
    v.business_unit_id IN (series of primary keys) 
GROUP BY v.vacancy_id 
HAVING v.vacancy_limit > count(b.booking_id) 
ORDER BY v.vacancy_id DESC 
+0

Cette condition n'est-elle pas satisfaite si la clause * (bs.booking_status_type_id = 1 OR bs.booking_status_type_id = 2) *? – nickd

+1

ce n'est pas suffisant car donner seulement la condition (bs.booking_status_type_id = 1 ou bs.booking_status_type_id = 2) correspondra aussi aux identifiants de réservation pour lesquels il pourrait y avoir des lignes pour les lignes rejetées ou révoquées – keshav84

+0

Keshu, je pense que vous avez peut-être raison. Plus j'y pensais hier, plus je me rendais compte que je ne filtrais pas le statut à l'avance. Je vais essayer de créer une base de données aujourd'hui et la tester car je ne suis pas au travail avant demain. –