Vous êtes sur la page 1sur 7

TECH 60701 -- Technologies de l'intelligence d'affaires

* HEC Montréal
* Travail Pratique 2
* Enseignant :
* J01 : Bogdan Negoita
*
* Instructions de remise :
* - Répondre aux questions SQL directement dans ce
fichier .sql
* - À remettre via ZoneCours dans l'outil de remise
de travaux
* - Date de remise : voir les dates sur ZoneCours,
aucun retard permis
*
* Correction :
* - 10% de la note finale, /10
* - Une question qui génère une erreur (ne
s'exécute pas) se verra attribuer automatiquement la note de 0.
* Par conséquent, testez votre code
fréquemment !
*/

use AdventureWorks2019
go

/*
Question #1 :
Le directeur de l’approvisionnement vient vous voir avec
une demande d'information. Il vous explique que tous les produits
d’AdventureWorks
sont en inventaire dans des entrepôts de l’entreprise.
Il aurait toutefois besoin de savoir quels sont les produits dont le
nombre en
inventaire est sous le niveau sécuritaire de stock
(SafetyStockLevel). Comme vous partez en vacances, il vous demande de
lui créer une vue
(vw_ProductInvDeficit) qui donnera cette info, comme ça
il pourra facilement aller chercher l’information durant votre absence.

Votre vue doit comprendre :


- L’ID du produit.
- Le nom du produit.
- La quantité totale actuellement en stock pour
le produit.
- Le niveau sécuritaire de stock du produit.
- La différence entre la quantité actuelle en
stock et le niveau sécuritaire de stock du produit.
- Le rang (acceptant des sauts de valeur) basé
sur la différence entre la quantité actuelle en stock et le niveau
sécuritaire de stock du produit.
Le produit où le déficit est le plus
important recevra le rang 1.
Le rapport ne doit comprendre que les produits dont le
niveau en stock est sous le niveau sécuritaire de stock et qui n'ont pas
de date prévue
de fin de vente.
*/

create view vw_ProductInvDeficit as


select
p.ProductID,
p.[Name],
sum(pinv.Quantity) as 'Quantité en dépôt',
p.SafetyStockLevel,
sum(pinv.Quantity) - p.SafetyStockLevel as 'Déficit de produit
en inventaire',
rank() over(order by sum(pinv.Quantity) - p.SafetyStockLevel) as
'Rang'
from Production.Product p
inner join Production.ProductInventory pinv on p.ProductID =
pinv.ProductID
where p.SellEndDate is null
group by p.ProductID, p.[Name], p.SafetyStockLevel
having sum(pinv.Quantity) - p.SafetyStockLevel < 0;

/*
Question #2 :
AdventureWorks aimerait mettre en œuvre le modèle de
vitalité ("The vitality model") de l'ancien président-directeur général
de General Electric,
Jack Welch, qui a été décrit comme un système "20-70-
10". Les "20% les plus importants" des employés sont les plus productifs
et 70% (les "70
indispensables") travaillent correctement. Les 10%
restants sont des non-producteurs et doivent être licenciés.

En utilisant une clause de classement et une sous-


requête, vous devez écrire une requête pour identifier les "20% les plus
performants" des commis
de vente (pour les féliciter et les encourager!) ainsi
que les 10% les moins performants (pour les mettre à la porte <insèrez
le rire diabolique ici>) !!
On ne veut donc pas voir apparaître dans le rapport les
commis de vente appartenant au 70% restant.

(On fait référence aux commis de vente, peu importe le


titre de poste.)

Comme AdventureWorks est essentiellement une entreprise


de vente au détail, le dernier trimestre de l'année (comprennant
l'Action de Grâce et Noël)
est crucial pour ses résultats financiers. Donc,
l'analyse doit uniquement tenir compte du sous-total des ventes que les
commis de vente ont réalisées
pour ce trimestre seulement, quelle que soit l'année. Il
faut afficher, pour chaque résultat :

- L'identifiant du commis de vente


- Le "National ID Number" du commis de vente
- Le prénom du commis de vente
- Le nom de famille du commis de vente
- La somme du sous-total vendu par le commis de
vente pour le quatrième trimestre (formaté en dollars, c.-à-d. $xxx.xx)
- Le rang en pourcentage du commis de vente
(formaté en pourcentage avec deux points de précision)
- Un message expliquant la signification du
classement en pourcentage (i.e., x,xx % de vos collègues ont fait mieux
que vous)
- Le décile auquel appartient le commis de vente
- Un message personnalisé pour : le 1er décile
'Excellente performance !'; le 2e décile 'Ça pourrait être mieux...'
le 10e décile 'Cherchez vous un emploi
ailleurs !'
*/

select
*,
Decile_Description =
case VirtualTable.Decile
when 1 then 'Excellente performance !'
when 2 then 'Ça pourrait être mieux...'
when 10 then 'Cherchez vous un emploi ailleurs !'
else 'Décile inconnu'
end
from
(
select
soh.SalesPersonID,
e.NationalIDNumber,
p.FirstName,
p.LastName,
format(sum(soh.SubTotal), 'c', 'en-us') as 'Somme du
sous-total vendu',
format(round(percent_rank() over(order by
sum(soh.SubTotal) desc), 2), 'p') as 'Rang en pourcentage',
concat(format(round(percent_rank() over(order by
sum(soh.SubTotal) desc), 2), 'p'), ' de vos collègues ont fait mieux que
vous') as 'Explication du pourcentage',
ntile(10) over(order by sum(soh.SubTotal) desc) as
[Decile]
from Sales.SalesOrderHeader soh
inner join Sales.SalesPerson sp1 on soh.SalesPersonID =
sp1.BusinessEntityID
inner join HumanResources.Employee e on sp1.BusinessEntityID =
e.BusinessEntityID
inner join Person.Person p on e.BusinessEntityID =
p.BusinessEntityID
where datepart(quarter, soh.OrderDate) = 4
group by soh.SalesPersonID, e.NationalIDNumber, p.FirstName,
p.LastName
) as VirtualTable
where VirtualTable.Decile in ('1','2','10')

/*
Question #3 :
AdventureWorks voudrait explorer les achats jumelés
effectués par ses clients. On s'interesse particulièrement aux autres
produits qui ont
été achetés en même temps qu'un "All-Purpose Bike Stand"
(ProductNumber ST-1401). Donc, les données doivent être affichées
seulement pour
les ventes faites aux clients qui ont achetés ce type de
support de vélo.

En utilisant une CTE, vous devez afficher une liste


contenant les informations groupées par l'identificateur du produit, le
nom du produit,
le numéro du produit.

Votre rapport doit contenir seulement quatre colonnes


comme suit:

ProductID |Name
|ProductNumber |OrderCount |Rang
873 |Patch Kit/8 Patches |
PK-7098 |98 |1
922 |Road Tire Tube
|TT-R982 |83 |2
921 |Mountain Tire Tube
|TT-M928 |54 |3
... |...
|... |... |...

Ceci indique par exemple que, pour l’ensemble des ventes


où un support de vélo a été acheté, 98 commandes incluaient également
l’achat du
produit 873 (Patch Kit/8 Patches), 83 commandes
incluaient l’achat du produit 922 (Road Tire Tube), etc. Le rang utilisé
ne permet pas
de sauts de valeur.

Trier par "OrderCount", par ordre décroissant.


*/

with MyCTE(SalesOrderID, SalesOrderDetailID) as


(
select
soh.SalesOrderID,
sod1.SalesOrderDetailID
from Sales.SalesOrderHeader soh
inner join Sales.SalesOrderDetail sod1 on soh.SalesOrderID =
sod1.SalesOrderID
inner join Production.Product p1 on sod1.ProductID =
p1.ProductID
where p1.ProductNumber = 'ST-1401' --la commande comprend
All-Purpose Bike Stand (ST-1401)
)
select
p.ProductID,
p.[Name],
p.ProductNumber,
count(distinct MyCTE.SalesOrderID) as OrderCount,
dense_rank() over(order by count(distinct MyCTE.SalesOrderID)
desc) as 'Rang'
from MyCTE
inner join Sales.SalesOrderDetail sod on sod.SalesOrderID =
MyCTE.SalesOrderID and sod.SalesOrderDetailID <>
MyCTE.SalesOrderDetailID
inner join Production.Product p on p.ProductID = sod.ProductID
group by p.ProductID, p.[Name], p.ProductNumber
order by 4 desc;

/*
Question #4 a) :
On vous demande de fournir une requête affichant les
détails suivants sur les fournisseurs actifs, sans statut privilégié,
chez
lesquels AdventureWorks a fait 30 commandes ou plus.
Affichez :
- L'identifiant du fournisseur
- La date de la commande
- Un numéro de séquence attribué à chaque
commande faite auprés du fournisseur, en débutant avec la plus récente
commande
- Le sous-total de chaque commande (formaté en
dollars, c.-à-d. $xxx.xx)
*/

select poh.VendorID
, poh.OrderDate
, row_number() over(partition by poh.VendorID order by
poh.OrderDate desc) as 'RowNum'
, format(poh.SubTotal, 'c', 'en-us') as 'Order subtotal'
from Purchasing.PurchaseOrderHeader poh
inner join Purchasing.Vendor v on poh.VendorID = v.BusinessEntityID
where v.ActiveFlag = 1
and v.PreferredVendorStatus = 0
and poh.VendorID in
(select VendorID from Purchasing.PurchaseOrderHeader group by
VendorID having count(PurchaseOrderID) >= 30)

/*
Question #4 b) :
AdventureWorks voudrait savoir qui parmi ces
fournisseurs réguliers (chez lesquels AdventureWorks a fait 30 commandes
ou plus) a
tendance à réduire ses prix. L'entreprise souhaite
utiliser ces informations afin de leur accorder le statut de
"fournisseur
privilégié". On émet ici l'hypothèse que les commandes
auprès d'un fournisseur restent stables à travers le temps et sont donc
toujours pour des produits/quantités similaires.

En utilisant une CTE basée sur la requête de la Partie


a), construisez une requête qui affichera la liste des fournisseurs pour
lesquels
le montant moyen (en utilisant le sous-total) de leurs
trois commandes les plus récentes est inférieur au montant moyen qu’ils
ont demandé
à AdventureWorks jusqu’à présent.

On voudra afficher :
- L'identifiant du fournisseur
- Le montant moyen des toutes les commandes
faites auprès du fournisseur
- Le montant moyen des trois commandes les plus
récentes faites auprès du fournisseur
- La différence entre le montant moyen des trois
commandes les plus récentes faites auprès du fournisseur et le montant
moyen des
toutes les commandes faites auprès du
fournisseur.

Votre rapport doit contenir seulement ces quatre


colonnes et être trié par la diminution relative aux coûts
d'acquisition, de façon
que la réduction la plus importante soit en tête de la
liste. Tous les montants doivent être formatés en dollars, c.-à-d.
$xxx.xx.
*/

with MyCTE(VendorID, OrderDate, RowNum, SubTotal) as


(
select poh.VendorID, poh.OrderDate
, row_number() over(partition by poh.VendorID order by
poh.OrderDate desc)
, poh.SubTotal
from Purchasing.PurchaseOrderHeader poh
inner join Purchasing.Vendor v on poh.VendorID =
v.BusinessEntityID
where v.ActiveFlag = 1
and v.PreferredVendorStatus = 0
and poh.VendorID in
(select VendorID from
Purchasing.PurchaseOrderHeader group by VendorID having
count(PurchaseOrderID) >= 30)
)
select MyCTE.VendorID
, (select format(avg(SubTotal), 'c', 'en-us') from
Purchasing.PurchaseOrderHeader poh where poh.VendorID = MyCTE.VendorID)
as 'Average Order Amount'
, format(avg(MyCTE.SubTotal), 'c', 'en-us') as 'Last 3 Orders
Average'
, format(avg(MyCTE.SubTotal) - (select avg(SubTotal) from
Purchasing.PurchaseOrderHeader poh where poh.VendorID = MyCTE.VendorID),
'c', 'en-ca') as 'Decrease in recent acquisition costs'
from MyCTE
where MyCTE.RowNum <= 3
group by MyCTE.VendorID
having avg(MyCTE.SubTotal) < (select avg(SubTotal) from
Purchasing.PurchaseOrderHeader poh where poh.VendorID = MyCTE.VendorID)
order by avg(MyCTE.SubTotal) - (select avg(SubTotal) from
Purchasing.PurchaseOrderHeader poh where poh.VendorID = MyCTE.VendorID)

Vous aimerez peut-être aussi