J'ai des données dans deux tables que je dois joindre et renvoyer le nombre d'occurrences d'un enregistrement dans l'une des tables,

Les données de la table Employee ressemblent à ceci:

empId  workpatternId
    1        20

Les données des tables workPattern ressemblent à ceci:

workpatternId  monday tuesday wednesday thursday friday saturday sunday
   20           ALL     ALL     ALL       ALL     NULL   NULL     ALL 

La requête suivante doit renvoyer 5, qui est le nombre de ALL, mais renvoie 7 à la place,

SELECT empId,b.workingPatternId, COUNT(monday='ALL') +
 COUNT(tuesday='ALL') + COUNT(wednesday='ALL')+ COUNT(thursday='ALL') + 
    COUNT(friday='ALL')+ COUNT(saturday='ALL')+ COUNT(sunday='ALL') AS COUNT
      FROM workPattern b 
 join Employee e on (e.workpatternId = b.workpatternId) and e.empId = 1
         GROUP BY empId ;

Quel est le problème avec la requête?

ÉDITER

dbfiddle

0
Bisoux 20 oct. 2020 à 11:41

3 réponses

Meilleure réponse

Je ne vois pas l'intérêt de l'agrégation, car il semble que vous n'ayez qu'une seule ligne dans workPattern par empId. Vous pouvez simplement écrire ceci comme suit:

SELECT e.empId, wp.workingPatternId, 
      (wp.monday    = 'ALL') 
    + (wp.tuesday   = 'ALL') 
    + (wp.wednesday = 'ALL') 
    + (wp.thursday  = 'ALL') 
    + (wp.friday    = 'ALL') 
    + (wp.saturday  = 'ALL') 
    + (wp.sunday    = 'ALL') cnt
FROM workPattern wp
INNER Employee e on e.workpatternId = wp.workpatternId 
WHERE e.empId = 1

Si vous avez besoin d'une agrégation pour une raison quelconque, alors vous voulez sum() plutôt que count(): ce dernier compte toutes les valeurs non nulles, tandis qu'une condition fausse est évaluée comme 0 (ce qui n'est pas { {X3}}, il est donc pris en compte dans votre requête):

SELECT 
    SUM(
          (wp.monday    = 'ALL') 
        + (wp.tuesday   = 'ALL') 
        + (wp.wednesday = 'ALL') 
        + (wp.thursday  = 'ALL') 
        + (wp.friday    = 'ALL') 
        + (wp.saturday  = 'ALL') 
        + (wp.sunday    = 'ALL')
    ) cnt
FROM workPattern wp
INNER JOIN Employee e on e.workpatternId = wp.workpatternId 
WHERE e.empId = 1
1
GMB 20 oct. 2020 à 17:10

Si les choix étaient limités à `` TOUS '' ou `` rien '', alors je ferais probablement quelque chose comme ça (avec un peu de PHP, juste pour le plaisir):

<?php

/*
DROP TABLE IF EXISTS employee_workpatterns;

CREATE TABLE employee_workpatterns
(employee_id INT NOT NULL
,workpattern INT NOT NULL
,UNIQUE(employee_id,workpattern)
);

INSERT INTO employee_workpatterns VALUES
(101,79);
*/

require('path/to/connection/stateme.nts');

$query = "
SELECT workpattern
  FROM employee_workpatterns
 WHERE employee_id = 101
 LIMIT 1
 ";

$stmt = $pdo->prepare($query);
$stmt->execute();

$result = $stmt->fetch();

$days = array('mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun');

for( $i=0; $i<7; $i++ ) {
    $daybit = pow(2,$i);
    if( $result['workpattern'] & $daybit ) {
        echo $days[$i] . ' ';
    }
}
// outputs mon tue wed thu sun 
?>

Si les choix sont plus compliqués, je construirais un tableau un peu comme suit:

workpattern day val
         20 mon ALL
         20 tue ALL
         20 wed HALF
         20 thu ALL
         20 sun ALL
-2
Strawberry 20 oct. 2020 à 09:12

Cela a fonctionné:

 SELECT empId,b.workingPatternId, sum(Monday='ALL') + sum(Tuesday='ALL') + sum(Wednesday='ALL')+ sum(Thursday='ALL') + sum(Friday='ALL') + sum(Saturday='ALL')+ sum(Sunday='ALL') AS COUNT
 FROM WorkPatterns b 
 JOIN Employee e 
        ON (e.workingPatternId = b.workingPatternId) 
        AND e.empId = 1   
 GROUP BY empId ;
0
GMB 20 oct. 2020 à 17:12