2017-09-19 2 views
0

Je suis supposé utiliser la base de données donnée (c'est assez énorme donc j'ai utilisé le partage de code) pour lister les noms et numéros de clients des 5% de clients les plus importants pour chaque branche. Pour trouver le top 5% des clients, j'ai décidé d'utiliser la fonction NTILE, (100/5 = 20, d'où NTILE 20). Les colonnes sont extraites de deux tables distinctes, j'ai donc utilisé les jointures internes. Pour la vie de moi, je ne peux pas comprendre où je vais mal. Je continue d'obtenir des erreurs "d'expression manquante" mais je ne sais pas exactement ce qui me manque. Voici la base de donnéesFonction NTILE et utilisation de la jointure interne dans Oracle

Base de données: https://codeshare.io/5XKKBj ERD: https://drive.google.com/file/d/0Bzum6VJXi9lUX1d2ZkhudTE3QXc/view?usp=sharing

Voici ma requête SQL jusqu'à présent.

SELECT 
    Ntile(20) over 
    (partition by Employee.Branch_no 
    order by sum(ORDERS.SUBTOTAL) desc 
    ) As Top_5, 
    CUSTOMER.CUSTOMER_NO, 
    CUSTOMER.LNAME 
FROM 
    CUSTOMER 
INNER JOIN ORDERS 
    ON 
    CUSTOMER.CUSTOMER_NO = ORDERS.CUSTOMER_NO 
GROUP BY 
    ORDERS.SUBTOTAL, 
    CUSTOMER.CUSTOMER_NO, 
    CUSTOMER.LNAME; 
+0

(1) il vous manque la table 'Employee'; (2) le 'GROUP BY' doit inclure toutes les expressions non-agrégées dans la clause' SELECT' (c'est-à-dire que vous agrégez 'ORDERS.SUBTOTAL' de sorte que vous ne pouvez pas l'inclure dans le' GROUP BY'); (3) envisager d'utiliser une sous-requête pour assembler les données source avant d'appliquer le 'NTILE'. –

+0

N'utiliserait pas Employee.Branch_no équivaudrait à avoir une table dedans? La seule chose que je peux penser est d'utiliser une autre jointure interne, mais cela semble être un gaspillage. Pouvez-vous s'il vous plaît expliquer la sous-requête? –

+0

Vous ne pouvez pas faire référence à une table qui n'est pas jointe. C'est ce que les jointures sont pour. –

Répondre

1

Vous devez joindre Employee et GROUP BY doit inclure toutes les expressions non agrégées. Vous pouvez utiliser un sous-requête pour générer les sous-totaux et obtenir le NTILE dans la requête externe, par exemple:

SELECT 
    Ntile(20) over 
    (partition by BRANCH_NO 
    order by sum_subtotal desc 
    ) As Top_5, 
    CUSTOMER_NO, 
    LNAME 
FROM (
    SELECT 
    EMPLOYEE.BRANCH_NO, 
    CUSTOMER.CUSTOMER_NO, 
    CUSTOMER.LNAME, 
    sum(ORDERS.SUBTOTAL) as sum_subtotal 
    FROM CUSTOMER 
    JOIN ORDERS 
    ON CUSTOMER.CUSTOMER_NO = ORDERS.CUSTOMER_NO 
    JOIN EMPLOYEE 
    ON ORDERS.EMPLOYEE_NO = EMPLOYEE.EMPLOYEE_NO 
    GROUP BY 
    EMPLOYEE.BRANCH_NO, 
    CUSTOMER.CUSTOMER_NO, 
    CUSTOMER.LNAME 
); 

Note: vous pouvez inclure BRANCH_NO dans la liste de sélection et, sinon la sortie regardera confusion avec dupliquer des clients (si un client a commandé des employés dans plusieurs succursales).

Maintenant, si vous voulez filtrer la requête ci-dessus pour obtenir juste le top 5%, vous pouvez mettre la chose dans un autre sous-requête et ajouter un prédicat sur la colonne Top_5, par exemple:

SELECT CUSTOMER_NO, LNAME 
FROM (... the query above...) 
WHERE Top_5 = 1;