2015-12-18 2 views
0

Je travaille donc avec un client pour implémenter un système similaire au système "badges and privileges" sur StackExchange. Bien que dans son système, elle cherche à utiliser des points et des récompenses pour son personnel. C'est le même principe de base. Les utilisateurs sont des points récompensés pour le bon travail d'équipe et gagnent des récompenses à partir de ces points. J'ai pensé qu'il serait utile d'ajouter le même type de fonctionnalité que SE utilise pour les afficher dans la barre de navigation supérieure, où il montre votre représentant et les badges dans l'ordre de la date à laquelle vous avez gagné l'un ou l'autre. C'est mon problème, j'ai trouvé de l'aide pour récupérer les données ensemble à partir des deux tables distinctes, mais je ne suis pas sûr de la façon dont je afficherais ces résultats dans l'ordre de la date d'obtention? A titre d'exemple:Données Echo SQL dans l'ordre de la date ajoutée en utilisant Union All

User ID #1 has earned 50 points on 18/12/2015 serait dans ap_user_points tableau

User ID #1 has earned 'The Gift Voucher' reward on '17/12/2015'

Si je simplement:

echo $row8['reward'] . $row8['points_added']

Il écho:

The Gift Voucher 50

Là où je besoin dans l'ordre par date:

50

The Gift Voucher

Si vous regardez votre représentant et icône BADGE dans la barre de navigation, vous verrez ce que je veux en venir ici, c'est un système similaire.

  <?php 
$user_id = $_SESSION['userid'];     
$sql8 = " 
SELECT r.reward_id,      
     r.user_id, 
     r.reward as reward, 
     r.date_earned as date_earned, 
     r.badge_desc, 

     NULL AS points_added,    
     NULL AS added_for, 
     NULL AS date_added 
    FROM ap_user_rewards as r 
    WHERE r.user_id = '$user_id' 

UNION ALL 

SELECT NULL, 
     NULL, 
     NULL, 
     NULL, 
     NULL, 

     p.points_added AS points_added, 
     p.added_for AS added_for, 
     p.date_added AS date_added 
    FROM ap_user_points as p 
    WHERE p.user_id = '$user_id' ORDER BY date_earned DESC, date_added DESC;"; 

    $result8 = $conn->query($sql8); 

     if ($result8->num_rows > 0) { 
      // output data of each row 
     while($row8 = $result8->fetch_assoc()) { 


      ////// NOT SURE WHAT TO ECHO HERE? 

    } 
} 
?> 
+0

Ce code semble être VULNERABLE à l'injection SQL. Utilisez ** des instructions préparées ** avec ** des espaces réservés **. Si vous ne pouvez pas le faire, exécutez au minimum la valeur potentiellement dangereuse '$ user_id' via une fonction de type' mysqli_real_escape_string' avant qu'elle ne soit incluse dans SQL. Comment est-il possible en 2015 que nous écrivions encore du code qui soit si ouvertement vulnérable à l'injection SQL? – spencer7593

+0

Ceci est juste un exemple de code pour avoir une idée approximative, c'est loin d'être terminé et j'ai juste besoin d'ajouter une idée de la façon dont je vais récupérer mes résultats. J'espère améliorer de manière significative les failles de sécurité avant la production. – Snappysites

Répondre

1

Ajouter une autre colonne au jeu de résultats. Dans cette nouvelle colonne, le remplir à partir des deux requêtes ... semble être l'expression date_added dans la première requête et l'expression date_earned dans la deuxième requête. Lorsque ceux-ci sont dans la même colonne, la commande est facile. (Cela suppose également que ces expressions sont des types de données identiques ou compatibles, de préférence DATE, DATETIME ou TIMESTAMP.)

Ensuite, vous pouvez commander par position ordinale, par ex. ORDER BY 2 pour commander par la deuxième colonne dans le jeu de résultats.

SELECT a1 
    , b1 
    , NULL 
    , NULL 
    , a1 AS sortexpr 
    FROM ... 
UNION ALL 
SELECT NULL 
    , NULL 
    , x2 
    , y2 
    , x2 AS sortexpr 
    FROM ... 
ORDER BY 5 DESC 

C'est juste une possibilité. Si vous ne pouvez pas ajouter une colonne supplémentaire, pour aligner les expressions des deux requêtes, vous avez besoin d'un moyen de discriminer quelle requête retourne la ligne. J'inclue généralement un littéral en tant que colonne discriminante.

Ensuite, vous pouvez utiliser la syntaxe UNION style implicite, enroulant les requêtes dans parens ...

(SELECT 'q1' AS `source` 
     , a1 
     , b1 AS date_earned 
     , NULL 
     , NULL AS date_added 
    FROM ... 
) 
UNION ALL 
(SELECT 'q2' AS `source` 
     , NULL 
     , NULL AS date_earned 
     , x2 
     , y2 AS date_added 
    FROM ... 
) 
ORDER BY IF(`source`='q1',date_earned,date_added) DESC 

Followup

j'ai mal compris la question. Je pensais que la question était de savoir comment obtenir les lignes d'un ALL UNION/UNION retourné dans un ordre particulier.

Personnellement, j'écrirais la requête pour inclure une colonne discriminante, puis aligner les colonnes autant que possible, afin qu'elles soient traitées de la même manière.

À titre d'exemple:.

SELECT 'reward'  AS `source` 
    , r.date_earned AS `seq` 
    , r.user_id  AS `user_id` 
    , r.date_earned AS `date_earned` 
    , r.reward_id 
    , r.reward 
    , r.badge_desc 
    , NULL   AS `points_added` 
    , NULL   AS `added_for` 
    FROM r ... 

UNION ALL 

SELECT 'points'  AS `source` 
    , p.date_added AS `seq` 
    , p.user_id  AS `user_id` 
    , p.date_added AS `date_earned` 
    , NULL 
    , NULL 
    , NULL 
    , p.points_added AS `points_added` 
    , p.added_for  AS `added_for` 
    FROM p ... 

ORDER BY 2 DESC, 1 DESC 

(Il est sans doute pas vraiment nécessaire de revenir user_id, puisque nous savons déjà ce que la valeur sera je suis retourné ici pour montrer comment les colonnes des deux resultsets peut être « alignés ».)

Puis, quand j'allé chercher les lignes ...

if ($row8['source'] == 'points') { 

     # process columns from a row of 'points' type 
     echo $row8['badge_desc']; 
     echo $row8['user_id']; 

    } elsif ($row8['source'] == 'reward') { 

     # process columns from a row of 'reward' type 
     echo $row8['added_for']; 
     echo $row8['user_id']; 

    } 

Voilà comment je le ferais.

+0

Donc, en utilisant ce système, comment pourrais-je 'echo' mes résultats pour les montrer dans le bon ordre comme' point, récompense, point, point, récompense, point' plutôt que dans des groupes comme 'point, point, point, récompense, récompense, récompense »comme je le sais si je fais juste écho récompense ou echo points_added cela ne fonctionnerait pas? – Snappysites

+0

Je pense avoir mal compris votre question. Je pensais que vous demandiez comment obtenir le resultset ordonné en SQL. L'approche que je voudrais utiliser est de retourner les lignes dans l'ordre que je veux les présenter, puis les présenter dans l'ordre où elles sont retournées. Je "aligner" les colonnes des deux requêtes. Si j'avais un traitement spécial, gérer les lignes d'une manière différente en fonction de la requête retournée, j'utiliserais une colonne discriminante. Sur la base de la valeur de cela, je gérerais les lignes d'une source et les lignes de l'autre source d'une autre manière, choisissez les colonnes à utiliser. – spencer7593