ASP.NET MVC: MSDN Mag Juillet

Le MSDN magazine du mois de juillet est dispo.

Si j'en parle ici c'est qu'il y a notamment plusieurs articles sur ASP.NET MVC:

Bonne lecture!



Classé sous , ,

SQL: TSQL Challenge #10

Voici déjà le dixième challenge de TSQL Challenges !

Je n'ai pas pris le temps de poster sur les solutions et gagnants des Challenges 6 et 7 mais je vous invite à voir mes posts sur celles-ci (en anglais): TSQL Challenge 6 et TSQL Challenge 7

Une mention spéciale à Aurélien de Wygwam, qui fait partie des gagnants du 6 et du 7, et une autre pour la petite histoire de baston Sql sur le challenge 6 avec Matthieu que l'on a publié ici.

Pour le Challenge #10, voici une traduction pour les francophiles.

En aparté du challenge proprement dit:
TSQL Challenges va désormais proposer du contenu gratuit sous forme de webcast afin d’aider les challengers qui ont un peu de mal à trouver la solution, et ainsi les aider à résoudre des problèmes similaires tout à fait concrets.

Le principe est le suivant:

  • Si vous pouvez résoudre le challenge, allez y, et envoyez votre solution !
  • Si vous n’y arrivez pas, inscrivez vous au webcast, il est gratuit et vous indiquera comment résoudre des problèmes ressemblant à celui du challenge. Le webcast ne sera en ligne qu'une fois le challenge clos. Tous les détails sont indiqués en bas de ce billet.

Le challenge 10

Ce challenge devrait être intéressant, car pour le résoudre, vous allez devoir trier les données horizontalement et verticalement.

Les données en entrée

  1. C1   C2   C3  
  2. ---- ---- ----  
  3. 2    1    3  
  4. 3    2    1  
  5. Z    X    Y  
  6. B    C    D  
  7. Y    Z    X  
  8. B    C    A  

Le résultat attendu

Voici ce qu’il faut produire en sortie. Il faut écrire une seule requête transformant les données d’entrée en données de sortie.

  1. C1   C2   C3  
  2. ---- ---- ----  
  3. 1    2    3  
  4. A    B    C  
  5. B    C    D  
  6. X    Y    Z  

Pour plus de clarté. Voici les différentes transformations:

  1. Trier les données horizontalement, en ordonnant les valeurs de la plus petite à la plus grande.
    Par exemple, la première ligne contient les valeurs “2”, “1” et “3”. Il va falloir les ordonner comme suit: ”1”, “2”, et “3”.
  2. Trier les lignes verticalement. Il s’agit du tri de lignes habituel. Les lignes doivent être ordonnées comme dans le listing du résultat attendu.
  3. Supprimer les doublons: les lignes identiques devront être éliminées du résultat.

Données d’exemple


Pour les données en entrée, vous pouvez utiliser ce script.

  1. DECLARE @t TABLE (  
  2.   c1 CHAR(1),  
  3.   c2 CHAR(1),  
  4.   c3 CHAR(1)  
  5. )  
  6.   
  7. insert into @t (c1, c2, c3) values ('2','1','3')  
  8. insert into @t (c1, c2, c3) values ('3','2','1')  
  9. insert into @t (c1, c2, c3) values ('Z','X','Y')  
  10. insert into @t (c1, c2, c3) values ('B','C','D')  
  11. insert into @t (c1, c2, c3) values ('Y','Z','X')  
  12. insert into @t (c1, c2, c3) values ('B','C','A')  
  13.   
  14. SELECT * FROM @t  

 

Remarques

Comme d’habitude, il faut produire le résultat attendu en une seule requête. Les CTEs sont autorisées.

  • Envoyez vos réponses à tc@beyondrelational.com
  • La date de clôture de ce challenge est le 29 juin 2009.
  • Utilisez ce forum pour poser toute question relative à ce challenge.
  •  

    Le webcast d’appentissage gratuit

    Avec ce challenge, nous commençons à inclure un webcast gratuit afin d’aider les challengers ne trouvant pas la solution. Le webcast aura lieu juste après la clôture du challenge.
    Les challengers ayant profité du webcast peuvent bien sûr envoyer leur solutions, mais elles seront évalués séparément.
    Les gagnants du challenge seront parmi ceux n’ayant pas assisté au webcast, et ayant donc envoyé leur solution avant la clôture du challenge. Si nous apprécions une solution parmi celles proposées par les challengers ayant bénéficié du webcast,  nous la publierons, mais le challenger ne sera pas identifié parmi les gagnants.

    Le webcast n’aura par pour but premier de résoudre le challenge. Mais plutôt d’expliquer comment écrire une requête ensembliste transformant des données sous la forme A en données sous la forme B. Ces techniques et astuces pourront être utilisées pour résoudre le challenge :-)

    Vous pouvez vous inscrire au webcast à l’adresse suivante : http://tsqlchallenge10.eventbrite.com/

    Amusez vous bien.


    Classé sous , ,

    DSL: Mise à jour de M

    J'ai l'impression que c'est passé un peu à la trappe, mais une nouvelle CTP d'OSLO est sortie le mois dernier.

    vous pouvez la télécharger ici: Oslo May 2009 CTP.

    So, what's new?
    Voici quelques nouveautés en vrac car je n'ai pas encore eut le temps de m'y plonger plus sérieusement:

    • Tout d'abord "Quadrant", un outil de modélisation graphique
    • la grammaire: apparition du '::' pour déterminer plus finement le scope d'un élément dans un module (ou langue), remplacement du '=' par '=>' pour l'affectation des valeurs.
    • Je ne sais pas si c'est uniquement à cause de Quadrant mais le sdk passe de ~10Mo à ~40Mo...
    • Le repository: sont maintenant inclus directement plusieurs modèles pouvant être utilisés comme base de language (et accessoirement comme références) comme Language.Catalog, Microsoft.Uml2 ou System.Runtime:

    Je ne sais pas si cela augure d'une nouvelle génération d'installeurs chez Microsoft mais celui-là est particulièrement beau, cela n'a rien à voir je sais mais j'aime bien ;-).

    VELOCITY
    Dans la même veine, je n'ai pas eu beaucoup d'échos là-dessus mais pour ceux qui auraient encore une CTP2, la CTP 3 de Velocity est dispo: Velocity CTP3.



    Classé sous

    ASP.NET MVC: For Visual Studio 2010 Beta 1

    La beta de Visual Studio 2010 n'est pas livrée avec les addon ASP.NET MVC comme ont pu le constater ceux qui s'y sont essayé. La raison est simplement que la version finale de MVC n'était pas prête au moment du package de la beta de Visual Studio. Pour remédier à cela un installeur séparé est disponible depuis aujourd'hui sur CodePlex. Il est estanpillé ASP.NET MVC 1.1 mais il s'agit juste d'une v1.0 pour 2010.

    Vous pourrez le retrouver ici: http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=28527. N'oubliez pas bien sur de lire les release notes qui vont avec ainsi que de télécharger les snippets spécifiques pour ASP.NET MVC.

    En cas de problème d'installation un petit guide d'aide est disponible ici.

    La beta 2 de Visual Studio 2010 intégrera bien sur directement ce package.



    Classé sous ,

    jQuery: Behaviour Driven Html

    A la question "ce serait pas mal sur certains liens de l'application spécifiques que l'utilisateur aie une boite de confirmation...", il y a bien sur plein de manières différentes de réponde et cela ne pose absolument aucune contrainte technique.


    Néanmoins c'est l'occasion de parler d'une technique que j'aime beaucoup qui est le "Behaviour Driven Html". Que ce cache derrière ce nom barbare? Il s'agit simplement d'affecter des comportements à des éléments d'une page html à travers des sélecteurs css. En combinant cela à la puissance de jQuery pour la manipulation de ces sélecteurs, cela permet plus particulièrement de se faire des petits frameworks génériques et de séparer les dépendances par rapports à des éléments clairement identifiés dans le code html.


    Pour répondre à notre question initiale de manière traditionnelle, quelles sont les approches les plus courantes?

    • ajouter du code javascript pour la confirmation dans l'attribut onclick de notre lien
    • créer une fonction générique de confirmation et l'appeler dans le onclick du lien
    • changer le comportement du lien par javascript en faisant référence à son id.

     

    La solution Behaviour Driven Html permet de séparer de manière élégante le code d'affichage html de son comportement. Pour cela, on utilise le fait de décorer un élément html par une ou plusieurs classes css. Il est d'usage dans les bonnes pratiques css de distinguer les différents types d'attributs. Par exemple, on utilisera une classe css normale pour le positionnement d'un élément et on utilisera une classe spécifique partagée pour la couleur. Ceci permet de découpler la palette des couleurs du site du reste et de rentre ainsi la mise à jour plus simple (cela permet aussi de changer les couleurs du theme d’un site simplement sans changer tout le reste du css…).

    Pour notre problème voila, je code jQuery que j’utiliserai:

    /**********************************************************************************
         CSS Selectors helpers Helpers
     **********************************************************************************/
     $('.WithConfirm').live('click', function(item) {
             return window.confirm('Do you want to continue?');
     });

    Puis à l’utilisation dans le Html:

    <a class="linkButton WithConfirm" href="/some/where">Delete</a>

    Pour revenir sur le petit bout de code jQuery:

    • Sur les handlers d’action jQuery, si la fonction retourne false, elle s’arrête là, si elle retourne true, elle continue la séquence avec les autres actions définie. Dans notre cas il s’agit d’un lien, donc l’action par défaut est ‘ouverture du lien sur click’. La boite de confirm nous retournant vrai ou faux, cela permet directement soit de s’arrêter et de ne rien faire soit poursuivre par le suivit du lien normalement.
    • J’utilise le helper live pour gérer le click à la fois sur des éléments existants mais aussi sur des futurs éléments que je pourrais être amené à construire dynamiquement sur ma page.
    • De part sa construction simple ce code fonctionnera aussi bien avec les liens qu’avec les boutons de submit de formulaire.

     

    Il est évident que l’on ne peut pas faire ça pour tout et n’importe quoi mais cela reste une mécanique très sympathique dans beaucoup de situations.


    Classé sous , ,

    TSQL Challenge 8

    Le  huitième challenge TSQL de TSQL Challenges est en ligne.

    Merci à Antoine pour les traductions FR ;-)

    Nous allons nous intéresser à une problématique classique des bases de données: les arborescences.

    SQL Serveur 2008 à introduit le type HierarchyID qui apporte à T-SQL le support de ce type d’information. Il s’agit d’un type managé contenant le chemin d’un nœud d’arborescence.

    Pour intéressant que ce type soit, le challenge sera de résoudre le problème sans utiliser HierarchyID, un peu comme le challenge 3 ou il fallait implémenter REVERSE() sans l’utiliser !

    Le problème

    Il faut retrouver les employés sous la responsabilité directe ou indirecte d’un manager.
    Voici l’organigramme de la société:

    1. /*  
    2. Jacob     
    3.     Jess     
    4.     Steve        
    5.         John     
    6.     Bob        
    7.         Michael        
    8.         Paul  
    9. Rui     
    10.     Smith        
    11.         Lana        
    12.         Johnson     
    13.     Bobbey        
    14.         Mic        
    15.         Stev  
    16. Jacobson  
    17.     Steffi  
    18.         Paulson  
    19.     Bracha  
    20.         Jessica  
    21. */  

     

    Le challenge

    Vous devez écrire une requête prenant un nom de manager en entrée et fournissant la liste des employés sous sa responsabilité directe ou indirecte, en indentant à l’aide de 4 espaces.

    Par exemple, si le nom du manager est “Smith”, le résultat renvoyé doit être

    1. /*  
    2. Smith        
    3.     Lana        
    4.     Johnson    
    5. */  

     

    si le nom du manager est “Jacob”, la requête doit renvoyer

    1. /*  
    2. Jacob     
    3.     Jess     
    4.     Steve        
    5.         John     
    6.     Bob        
    7.         Michael        
    8.         Paul  
    9. */        

    Données et début du script

    Voici les données et le début du script. A vous de compléter !

    1. DECLARE @Employees TABLE (EmpID INT, EmpName VARCHAR(20), ReportsTo INT)  
    2. INSERT INTO @Employees(EmpID, EmpName, ReportsTo)      
    3. SELECT 1, 'Jacob'NULL UNION ALL      
    4. SELECT 2, 'Rui'NULL UNION ALL      
    5. SELECT 3, 'Jacobson'NULL UNION ALL      
    6. SELECT 4, 'Jess', 1 UNION ALL      
    7. SELECT 5, 'Steve', 1 UNION ALL      
    8. SELECT 6, 'Bob', 1 UNION ALL      
    9. SELECT 7, 'Smith', 2 UNION ALL      
    10. SELECT 8, 'Bobbey', 2 UNION ALL      
    11. SELECT 9, 'Steffi', 3 UNION ALL      
    12. SELECT 10, 'Bracha', 3 UNION ALL      
    13. SELECT 11, 'John', 5 UNION ALL      
    14. SELECT 12, 'Michael', 6 UNION ALL      
    15. SELECT 13, 'Paul', 6 UNION ALL      
    16. SELECT 14, 'Lana', 7 UNION ALL      
    17. SELECT 15, 'Johnson', 7 UNION ALL      
    18. SELECT 16, 'Mic', 8 UNION ALL      
    19. SELECT 17, 'Stev', 8 UNION ALL      
    20. SELECT 18, 'Paulson', 9 UNION ALL      
    21. SELECT 19, 'Jessica', 10  
    22.   
    23. DECLARE @manager VARCHAR(20)  
    24. SELECT @manager = 'Smith'  
    25. -- Votre SELECT ici  

     

    Une petite complication

    Le requête un un peu trop facile à écrire en utilisant une CTE récursive.On va donc ajouter une restriction:

    “La requête doit utiliser une CTE récursive, le filtre sur la variable "@manager” ne devra pas être appliqué dans la CTE”.

     

    Notes

    • La requête doit fonctionner sous SQL Serveur 2005 et 2008.
    • Il ne doit y avoir qu’une seule requête, pas de tables temporaires, de fonctions, etc.
    • Les employés du même nœud parent peuvent être triés par EmpName ou par EmpID  (ils sont triés par EmpID dans les exemples).
    • Envoyez vos réponses à tc@beyondrelational.com avec ‘TSQL Challenge 8’ comme sujet, et votre script en pièce jointe (fichier prenom_nom_tsqlchallenge8.sql)
    • Vous pouvez envoyer vos réponses jusqu’au 1er juin 2009.

     

    Ce forum est dédié aux questions générales au sujet des challenges TSQL.
    Ce forum est dédié au challenge 8.


    Classé sous ,

    TSQL Challenge 7

    Le 7ème challenge de la série est disponible sur TSQL Challenges.

    Je relaie un peu tard ce challenge (alors que c'est moi qui l'ai rédigé, c'est un comble...), mais du coup je vais étendre la date de fin de participation au 28 Mai.

    Le contexte

    Vous avez développé une solution SQL Serveur pour une petite société qui possède une serveur SQL hébergeant plusieurs bases de données. Avant votre départ, comme la société n’a pas de DBA, il faudrait que vous écriviez un petit script permettant à cette entreprise de surveiller la taille de ses données.

    Le challenge

    Il s’agit de de trouver quelles sont les 5 tables les plus grosses (au niveau données utiles), toutes bases de données utilisateurs confondues.

    Le résultat doit inclure les colonnes suivantes:

    • BASE: le nom de la base de données,
    • TABLE: le nom de la table,
    • SIZE: la taille des données, en KB (seulement des données, pas les indexes ni l’espace réservé),
    • ROWS: le nombre de lignes de la table (ce qui permettra de savoir si la table est grosse parce qu’elle possède des lignes de grande taille ou parce qu’elle contient beaucoup de lignes).

     

    Voici un exemple de résultats:

    1. BASE     TABLE   SIZE        ROWS        
    2. ----------------------------------  
    3. base1    T1      162720 KB   14233         
    4. base2    T2      38000 KB    8462         
    5. base1    T3      10720 KB    5343          
    6. base1    T4      9040 KB     5006         
    7. base3    T5      2800 KB     1899    

    Comme pour le challenge 4, il s’agit d’écrire le code le plus court possible. Le seul critère d’évaluation est le nombre de caractère du code, donc n’essayez pas de rendre votre code lisible !

    Notes:

    • Vous pouvez utiliser n’importe quelle technique offerte par une installation standard de SQL Serveur (2000, 2005, 2008).
    • Le script n’est pas limité à une seule requête.
    • Si vous créez des tables temporaires, des procédures, …, il faudra les supprimer à la fin de votre script. 
    • Le résultat de votre script doit être un jeu de données (pas de print), car on doit pouvoir le réutiliser, par exemple pour envoyer ces résultats par mail toutes les 5 minutes à l’aide d’un job.
    • Envoyez vos réponses à tc@beyondrelational.com
    • Ne collez pas votre code dans le corps du mail. Créez plutôt un fichier  “prenom_nom_tsqlchallenge7.sql” et envoyez le en pièce jointe.
    • Le titre du mail doit contenir  ‘TSQL Challenge 7’.
    • Il y a un thread de discussions générales sur la série des challenges TSQL.
    • Il y a aussi un thread de discussion propre à ce challenge 7.


    Classé sous ,

    TSQL Challenge 6

    Je n’ai pas eu le temps d’adapter une version fr du challenge, donc je vous livre la version que j’ai postée sur Beyond Relational telle quelle. Comme d’habitude vous pouvez m’envoyer vos solutions sur challenge at rui point fr.

    The context

    For this challenge, you will have to analyse logs on the web server of your company.


    Here is the sample data you have to work with:

    ID          VisitDate               Page            NbVisitors   
    ----------- ----------------------- --------------- -----------   
    1           2009-03-23 00:00:00.000 Home            10  
    2           2009-03-24 00:00:00.000 Home            14  
    3           2009-03-26 00:00:00.000 Home            22  
    4           2009-03-27 00:00:00.000 Home            3  
    5           2009-03-29 00:00:00.000 Home            4  
    6           2009-04-01 00:00:00.000 Home            33  
    7           2009-04-03 00:00:00.000 Home            2  
    8           2009-03-26 00:00:00.000 Contact         22  
    9           2009-03-27 00:00:00.000 Contact         10  
    10          2009-03-29 00:00:00.000 Contact         35  
    11          2009-03-30 00:00:00.000 Contact         13  
    12          2009-03-27 00:00:00.000 Products        8  
    13          2009-03-29 00:00:00.000 Products        12  
    14          2009-04-01 00:00:00.000 Products        16  
      

    The Challenge

    There is an existing application that takes tabular data with hierarchical consolidation inside. Your boss ask you to produce a report about web site activity using this application. In order to use the hierarchical capabilites of this application, each row of the report you provide needs to have an id and hierarchical level information. The Id is a construction based on year, week number and day in week number. For each consolidation row A T is added at the end (see the resulting table).


    The key point of this report is to count for each day, each week, each year, the number of visitors of each page of the site. A period label should be also produced with the following format : '3 letter of the name of the day in week' day / month (exemple: MON 23/3) for the day rows, TOTAL WEEK XX (exemple TOTAL WEEK 25) for the week rows and finally TOTAL YEAR XXXX for the year rows.
    We supose that we only have 3 sections on the site corresponding to Home,Contact and Products. This should be considered as static information and will not be updated in the future.


    This is the resulting table corresponding to this data you have to produce to fit with the reporting application:

    PERIOD_ID  LEVEL PERIOD          HOME        CONTACT     PRODUCTS    
    ---------- ----- --------------- ----------- ----------- -----------    
    2009131    0        MON  23/3    10          0           0    
    2009132    0        TUE  24/3    14          0           0    
    2009134    0        THU  26/3    22          22          0    
    2009135    0        FRI  27/3    3           10          8    
    2009137    0        SUN  29/3    4           35          12    
    200913T    1     TOTAL WEEK 13   53          67          20    
    2009141    0        MON  30/3    0           13          0    
    2009143    0        WED  1/4     33          0           16    
    2009145    0        FRI  3/4     2           0           0    
    200914T    1     TOTAL WEEK 14   35          13          16    
    2009T      2     TOTAL YEAR 2009 88          80          36   

    With this data I can open the report with all nodes closed, only the year total appears, then I can drill through total weeks and week days.
    Notes:

    • You should write this in any number of queries to produce the final correct table (but solutions with only one query will have better notes), the pnly limitation is that it should work inside a user function and be queryable as a single query.
    • You have to use only pure T-SQL, no CLR, or Reporting Services.
    • The Query should target any version of Sql Server (but a solution that works on all will be prefered)
    • You have to use the exact sample data provided (please don't re-write the sample data with your naming,etc...)
    • Last Date: 18 May 2009

     


    Sample Data:

    SET DATEFIRST 1    
    SET DATEFORMAT YMD    
    SET NOCOUNT ON    
    DECLARE @T TABLE (ID INT IDENTITY(1,1), VisitDate DATETIME, Page NVARCHAR(15),NbVisitors INT)    
    INSERT INTO @T (VisitDate,Page,NbVisitors) VALUES ('2009-03-23','Home',10)    
    INSERT INTO @T (VisitDate,Page,NbVisitors) VALUES ('2009-03-24','Home',14)    
    INSERT INTO @T (VisitDate,Page,NbVisitors) VALUES ('2009-03-26','Home',22)    
    INSERT INTO @T (VisitDate,Page,NbVisitors) VALUES ('2009-03-27','Home',3)    
    INSERT INTO @T (VisitDate,Page,NbVisitors) VALUES ('2009-03-29','Home',4)    
    INSERT INTO @T (VisitDate,Page,NbVisitors) VALUES ('2009-04-01','Home',33)    
    INSERT INTO @T (VisitDate,Page,NbVisitors) VALUES ('2009-04-03','Home',2)    
    INSERT INTO @T (VisitDate,Page,NbVisitors) VALUES ('2009-03-26','Contact',22)    
    INSERT INTO @T (VisitDate,Page,NbVisitors) VALUES ('2009-03-27','Contact',10)    
    INSERT INTO @T (VisitDate,Page,NbVisitors) VALUES ('2009-03-29','Contact',35)    
    INSERT INTO @T (VisitDate,Page,NbVisitors) VALUES ('2009-03-30','Contact',13)    
    INSERT INTO @T (VisitDate,Page,NbVisitors) VALUES ('2009-03-27','Products',8)    
    INSERT INTO @T (VisitDate,Page,NbVisitors) VALUES ('2009-03-29','Products',12)    
    INSERT INTO @T (VisitDate,Page,NbVisitors) VALUES ('2009-04-01','Products',16)   

    Classé sous ,

    TSQL Challenge 5 winners

    J'ai passé pas mal de temps a analyser les solutions proposées par tout le monde (à la fois celles envoyées pour ce post et celles sur Beyond Relational

    Je compléterai ultérieurement par des posts plus explicites pour montrer certaines solutions particulièrement intéressantes.

    Pour les challengers fr voici la liste des gagants:

    Le point de départ de ce challenge était de voir comment il était possible d’adapter la fonction sql split (que tout développeur Sql a au moins une fois du mettre en pratique ;-), en mode intégré à une requête.

    L’exercice est pour le moins intéressant car la problématique de valeurs séparées par des virgules devant être traitées par du Sql est finalement assez courante (même si pas forcément une bonne pratique…).

    Si on se place d’un point de vue pratique, cette solution permettrai par exemple d’implémenter simplement une liste d’auto-complétion sur un champ de recherche par rapport à des tags coté serveur.

    Souvent comme les listes de valeurs ne sont pas pratiques à transmettre entre le code applicatif et le sql, on déplace le problème coté applicatif and manipulant les listes d’objets correspondants. Il serait très pratique dans le cas présent, d’implémenter une petite requête linq qui parse à la fois la liste de tags prédéfis et ceux associés aux posts, mais cela ne serait certainement la plus performante.

    Voici donc ma solution initiale:

    ;WITH FILTER (id , data, VALUE) AS (
        SELECT    id,data = CAST(data AS NVARCHAR(MAX)),VALUE = CAST('' AS NVARCHAR(MAX))
        FROM @filter
        UNION ALL
        SELECT    id, data =    CASE WHEN CHARINDEX(',',data) > 0
                            THEN SUBSTRING(data,CHARINDEX(',',data)+1,LEN(data)-CHARINDEX(',',data))
                            ELSE '' END
                , VALUE =    CASE WHEN CHARINDEX(',',data) > 0
                            THEN SUBSTRING(data,1,CHARINDEX(',',data)-1) ELSE data END
        FROM FILTER
        WHERE LEN(data) > 0
    ),
     BLOG_TAGS (id , tags, VALUE) AS (
        SELECT    id,tags = CAST(tags AS NVARCHAR(MAX)),VALUE = CAST('' AS NVARCHAR(MAX))
        FROM @blog
        UNION ALL
        SELECT    id, tags =    CASE WHEN CHARINDEX(',',tags) > 0
                            THEN SUBSTRING(tags,CHARINDEX(',',tags)+1,LEN(tags)-CHARINDEX(',',tags))
                            ELSE '' END
                , VALUE =    CASE WHEN CHARINDEX(',',tags) > 0
                            THEN SUBSTRING(tags,1,CHARINDEX(',',tags)-1) ELSE tags END
        FROM BLOG_TAGS
        WHERE LEN(tags) > 0
    )
    SELECT F.ID,F.data,B.name,B.tags,RELEVANCE = COUNT(B.ID)
    FROM(
        SELECT    F.ID,F.data,FILTER.VALUE
        FROM    FILTER INNER JOIN @filter F ON FILTER.ID = F.ID
        WHERE LEN(VALUE) > 0
    ) F
    INNER JOIN
    (
        SELECT    B.ID, B.name, B.tags,T.VALUE
        FROM    @blog B INNER JOIN BLOG_TAGS T ON B.ID = T.ID
        WHERE LEN(VALUE) > 0
    ) B ON F.VALUE = B.VALUE
    GROUP BY F.ID,F.data,B.name,B.tags
    ORDER BY F.ID,RELEVANCE DESC

    C’est une solution parmi d’autres, pas forcément la meilleure et je publierai ultérieurement les autres solutions commentées.

    En espérant que ce challenge vous ait plus et vous aie un peu plus éclairé sur la magie du sql ;-)

    Le prochain challenge est déja en ligne…


    Classé sous , ,

    ASP.NET MVC: petit questionnaire

    Kazi Manzur Rashid a publié aujourd’hui une série de petits questionnaires sur l’environnement d’utilisation d’ASP.NET MVC utilisé par chacun. Les résultats sont pour moi assez logiques finalement. Ce qui est vraiment éclatant c’est à quel point le framework ajax de Microsoft est délaissé au profit de jQuery, mais je vous laisse voir les résultats par vous mêmes (vous pouvez bien sur voter pour apporter votre pierre à l’édifice!):

    1. Which Javascript framework your ASP.NET MVC UI component should depend – jQuery Vs. ExtJS Vs. MS Ajax?
    2. Which View Engine do you use in ASP.NET MVC – Webform Vs. Spark Vs. NHaml Vs. ….?
    3. What kind of UI Components do you prefer for Webform View Engine - HtmlHelper Vs. Control?

    image

    (j’ai capturé les résultats actuels car la version Embedded pose quelques problèmes d’affichage sur CS…)

    Et vous?


    Classé sous , , , ,

    ASP.NET MVC Pratique #15: Comment bien commencer

    Suite à ma présentation d’hier sur ASP.NET MVC à Winwise, j’ai promis de fournir quelques éléments pour bien commencer.

    Commencer par un tutoriel ou un livre

     Comme toutes les technologies que l’on ne connait pas, il est très difficile au début d’en voir les tenants et aboutissants, de savoir par quel bout commencer ou encore de distinguer ce qui est pertinent de ce qu’il ne l’est pas.

    C’est pour cela que malgré notre ère techno-blog, un bon vieux bouquin qui vous prend par la main et qui vous explique comment cela marche a toujours une très forte valeur pédagogique.

    Les bons livres ne sont pas encore tout à fait dans les bacs, néanmoins dès qu’il sera disponible (mi-mai?) je vous conseille le livre de Scott Hanselman, Phil Haack, Rob Conery et bien sur Scott Guthrie: Professional ASP.NET MVC 1.0.

    Sur ce livre, le premier chapitre (180 pages), écrit par Scott Guthrie est un tutorial complet en prenant comme base l’application NerdDinner. Cet ebook est disponible gratuitement avec le code de l’application:

     

    Ce tutorial est vraiment très bon pour une première approche car le modèle de données est vraiment très simples (2 entités dans le modèle!) par contre l’application utilise l’intégralité (ou presque) de ce que l’on peut (doit) faire sur ASP.NET MVC. Vous pourrez retrouver aussi l’intégralité de cet ebbok sous forme Html ci-dessous:

     

    Pour compléter ces tutoriaux en ligne, je vous conseille les posts de Stephen  Walther issus de son livre ASP.NET MVC Framework Unleashed:

     

    Je complèterai la liste des livres par ASP.NET MVC in Action:


    Si les deux premiers livres cités sont très bons, ils restent malgré tout proches de la vision Microsoft des choses (tous les auteurs en sont). Manning sort d’une manière générale de très bon livres, la série “In Action” tout particulièrement et les auteurs sont connus et reconnus pour leurs qualités dans le monde open source et alternatif. Ils figurent notamment parmi les créateurs du framework ASP.NET MVC MVCContrib.

    De plus Manning sort ce livre avec le program MEAP qui vous permet d’accéder au livre électronique au fur et à mesure de son écriture. Cette version électronique est à 27$50, et peut être réduite de 32% si vous l’achetez avant le 5 mai avec un coupon (que je vous fournirai si vous me le demandez par mail). Ce qui avec la parité euro/dollar vous fait un très bon livre à 15€ ;-)…

     

    Analyser le code

    Une fois que vous savez un peu mieux de quoi il en retourne, le mieux pour se faire une idée de comment développer correctement avec ASP.NET MVC est de prendre le code source d’applications complètes.

    Attention toutefois, tout n’est pas bon à prendre!

    Il y a notamment deux projets plus ou moins promus par Microsoft qui ne sont pas au top et donnent parfois des exemples de mauvais usages (et pratiques):  Oxite et Kobe.

    Note: certaines parties d’Oxite restent intéressantes et jeter un œil dessus n’est pas complètement toxique ;-). Pour Kobe, une note est actuellement sur la page: en cours de mise à jour suite aux remarques de la communauté ;-).

    Je vous conseille donc au niveau des sources:

    • NerdDinner, on en a déjà parlé, mais il à l’avantage d’être à la fois simple et complet (il est fort le Gu…)
    • Kigg, qui est un clone de Digg pour .net (utilisé par dotnetshoutout.com)
    • MvcContrib, dont j’ai déja parlé aussi, qui est une librairie complémentaire à ASP.NET MVC qui apporte beaucoup de choses. Vous pouvez l’intégrer tel quel dans vos projets, mais la lecture des sources peut vous apporter un plus non négligeable.
    • Sharp Architecture, qui est un projet de démo et de présentation des bonnes pratiques autour de ASP.NET MVC avec NHibernate, Ninject,etc..

     

    Se tenir à jour avec les blogs

    Se tenir informé des techniques au jour le jour peut paraitre une évidence, mais c’est d’autant plus vrai avec un produit encore jeune. Vous n’apprendrez peut-être pas grand chose de plus après avoir lu tout ce que je viens de citer au-dessus, mais le framework est récent et les pratiques et usages restent encore un peu en friche. Il y en aura donc encore pour un moment avant que toutes les bonnes pratiques et solutions à tous les petits problèmes de tous les jours n’aient plus d’intérêt.

    Voici donc une liste non exhaustive des blogs que je vous conseille de surveiller si vous ne les suivez pas déjà pour d’autres raisons que ASP.NET MVC (en anglais of course):

     

    Et bien sur http://www.rui.fr pour de l’ASP.NET MVC en français dans le texte ;-).

    Voila pour ce post sur les ressources à connaître pour commencer ou maitriser ASP.NET MVC. J’espère pour compléter cela pouvoir mettre en ligne bientôt mes slides de présentation, les sources de mes petites démos (et peut être si le temps le permet un vrai bon gros tutorial).

    Enjoy!





    Classé sous , , , ,

    SQL: 2010, Kilimanjaro preview

    Ce jeudi Microsoft organise un webcast de présentation de ce que sera le futur Sql Server (code name 'Kilimanjaro').
    pour vous inscrire c'est ici: http://www2.eventsvc.com/academylive/register/95712536-abbb-4621-a484-33cb28bce69c

    "This session will provide you with an sneak preview into the next release of SQL Server codenamed ‘Kilimanjaro’ as well as project ‘Madison’ both of which will ship in the first half of CY 2010. This session will introduce at a high level the set of upcoming technologies in the areas of Self Service Business Intelligence, Application & Multi-Server Management and Scale-out Data Warehousing as well as several other key capabilities planned for the next release of SQL Server."
    Donc, le 30 avant de vous jeter sur les RC de Windows 7 et Windows Server 2008 R2 prévues ce jour là, gardez un peu de bande passante pour profiter de ce webcast (18-19h, heure de Paris)!;-)


    Classé sous , ,

    SQL: The Art Of XSD

    Un bouquin que je ne saurai que trop vous recommander si vous voulez vous documenter sur l'état de l'art de l'usage des schémas XSD au sein de SQL Server:



    Avant d'aller plus loin, je tiens à signaler qu'en dehors d'une petite inscription sur le site de Red-Gate, le livre est GRATUIT.

    Ce livre conséquent de 500 pages, écrit par Jacob Sebastian (avec qui je publie les Challenges SQL ;-)) est un des plus complets sur le sujet. Ce sujet n'ayant droit d'une manière générale qu'à un chapitre rapide dans les livres génériques sur SQL Server.

    Sans pour autant avoir envie de devenir un spécialiste des schémas sur Sql Server, le sujet est relativement intéressant et gagne à être mieux connu. D'autant qu'il y a souvent une certaine ambiguité et/ou incompréhension entre données relationnelles et données XML. Savoir manipuler des données XML en base est une chose, savoir leur donner tout leur sens à l'aide de schémas en est une autre.

    Voici le sommaire des chapitres du livre:
    • Chapter 1: This chapter gives an introduction to XML schema, discusses a few different schema languages, and then explains the XML support extended by SQL Server 2000, 2005 and 2008.
    • Chapter 2: In this chapter we will write our first XSD schema. We will then have a look at XML namespaces and become familiar with SQL Server XML Schema collections. We will see how to validate XML instances against schema collections and will have a quick overview of the SSMS XSD editor.
    • Chapter 3: This chapter presents a fictitious company, North Pole Corporation, which needs some web services developed for their order processing application. This chapter identifies the structure of the XML data to be exchanged and determines the validations to be performed using XSD.
    • Chapter 4: This chapter explains the basic building blocks of XSD. We will see Element Declarations, Attribute Declarations, Simple Types, Complex Types, Attribute Groups, Element Groups, Order Indicators, Occurrence Indicators, annotations, etc. This chapter also explains how to associate data types with element declarations and perform additional validations on the value of elements and attributes.
    • Chapter 5: This chapter explains element declarations in detail. We will examine global and local element declarations and discuss each attribute that an element declaration can take. We will examine name, id, type, default, fixed, nillable, substitutionGroup, abstract, block, final, minOccurs, maxOccurs, ref and form attributes.
    • Chapter 6: This chapter explains attribute declarations in detail. We will have a quick glance into the behavior of elements and attributes and will discuss global and local attribute declarations. We will then look at each parameter of an attribute declaration and will discuss attribute groups and their usages.
    • Chapter 7: This chapter starts with a basic discussion on the importance of data types. We will discuss the characteristics of XSD data types and XSD Primitive Data Types in much detail.
    • Chapter 8: This chapter focuses on Simple Types. It explains the difference between simple types and complex types and discusses local and global simple type declarations. We will examine simple type derivation as well as the enhancements added to list and union types in SQL Server 2008. We will also examine how to restrict derivation of simple types.
    • Chapter 9: We will discuss XSD Derived Data Types in this chapter. This chapter starts with a discussion on XSD Primitive Data types and Derived data types and then discusses the facets of the primitive data types. Finally, it explains each of the Derived Data Types in detail.
    • Chapter 10: We will examine Complex Types in this chapter. We will examine local and global complex types and discuss the different content models of complex types. We will also examine order indicators, occurrence indicators and element groups.
    • Chapter 11: This chapter focuses on derivation of complex types. It discusses the derivation of each content model by restriction as well as by extension. It also explains how to control complex type derivation.
    • Chapter 12: This chapter explains the Regular Expression language supported in XSD. We will discuss regular expressions, patterns, meta characters, case sensitivity, shorthand character classes, negative expressions and character class subtraction.
    • Chapter 13: This chapter discusses some advanced XSD concepts. We will discuss element wildcards, attribute wildcards, and extension of wildcard elements and attributes. We will see different ways a schema processor validates wildcard declarations. We will then see the different attributes of a schema declaration.
    • Chapter 14: This chapter looks closer into XML Schema Collections.We will discuss how to create schema collections having more than one schema definition. We will then discuss how to alter schema collections, how to retrieve the definition of a schema collection from SQL Server and will examine the various system catalog views related to schema collections.
    Lien vers l'annonce de Jacob et téléchargement

    Bon xsd ;-)


    Classé sous , , , ,

    TSQL Challenge 5

    Voici un nouveau challenge sql que j’ai cross posté aussi sur Beyond Relational avec Jacob Sebastian. Je travaille maintenant avec lui à la rédaction de nouveaux challenges sql. Un nouveau blog dédié ainsi qu’un forum ont été ouverts spécialement pour l’occasion.

    Il s’agit ici d’étudier comment transformer des données séparées par des virgules en données tabulaires, mais le tout en ligne, en une seule requête.

    Le contexte

    Vous devez faire un rapport sur des recherches par mots clés sur un blog.

    Le moteur de blog enregistre l’ensemble des mots clés d’un post dans un champ ‘tags’:

    exemple de données du blog:

    id          name                 tags
    ----------- -------------------- --------------------
    1           post 1               sql,profiler,table
    2           post 2               sql,performance
    3           post 3               profilter
    4           post 4               view,table

     

    Chaque fois que quelqu’un fait une recherche par mots clés, une table de cache de ces ensembles de mots clés est stockée en base pour fournir ultérieurement des données à la fonctionnalité d’auto-suggestion du champ de recherche.

    exemple de donnée de cette table:

    id          data
    ----------- --------------------------------
    1           sql,performance
    2           profiler
    3           table,performance,view

     

    Le challenge

    Vous devez trouver pour chaque recherche effectuée dans la table d’historique tous les posts correspondants en indiquant le nombre de mots clés correspondants. Un post correspondant à la recherche doit contenir au moins un mot clé associé figurant dans la liste des mots clés de la recherche.

    Par rapport aux exemples de données précédents voici la table résultante que vous devez trouver:

    ID data                    name     tags                 RELEVANCE
    -- ----------------------- -------- -------------------- -----------
    1  sql,performance         post 2   sql,performance      2
    1  sql,performance         post 1   sql,profiler,table   1
    2  profiler                post 1   sql,profiler,table   1
    3  table,performance,view  post 4   view,table           2
    3  table,performance,view  post 1   sql,profiler,table   1
    3  table,performance,view  post 2   sql,performance      1
    1. Conditions:
    • Vous devez écrire une seule requête pour aboutir au résultat souhaité.
    • Merci d’utiliser le code d’exemple ci-dessous pour votre requête et de tester qu’elle fonctionne correctement avec celui-ci
    • envoyez vos solutions par mail sur challenge at rui point fr
    • Pour éviter les erreurs envoyez vos solutions dans un fichier .sql attaché à votre mail avec les données fournies et votre solution.
    • Vous avez jusqu’au 1er mai 2009 pour envoyer vos réponses
    • vous pouvez poser vos questions dans les commentaires (vos réponses par mail uniquement)

     

    Merci et bon challenge!


    Sample Data:

    DECLARE @filter TABLE (id INT IDENTITY, data nvarchar(32))
    insert into @filter (data) values ('sql,performance')
    insert into @filter (data) values ('profiler')
    insert into @filter (data) values ('table,performance,view')
     
    DECLARE @blog TABLE (id INT IDENTITY, name nvarchar(20), tags nvarchar(20))
    insert into @blog (name,tags) values ('post 1','sql,profiler,table')
    insert into @blog (name,tags) values ('post 2','sql,performance')
    insert into @blog (name,tags) values ('post 3','profilter')
    insert into @blog (name,tags) values ('post 4','view,table')

    SQL: Réponses au challenge #03

    Pas mal de (bonnes) réponses pour ce troisième challenge, toutes aussi diverses et intéressantes.

    Bravo donc à Nicolas, Arnaud, et Joel qui sont les 3 gagnants de ce challenge et qui m'on soumis les solutions les plus intéressantes.

    Pour rappel vous trouverez le détail du challenge ici.

    Ce challenge peut-être résolu avec ou sans CTE. Je ne l'ai pas spécifié pour justement laisser cette liberté mais je préfère une solution avec CTE car elle permet une plus grande lisibilité et évolutivité du code. En effet avec elle vous pouvez spécifier le nombre max de coupons à utiliser sous forme de paramètre alors que sans il faut coder en dur une sélection par coupon.

    Voici donc le code de la solution que je vous propose avec le jeu d'exemple:

    DECLARE @T TABLE (ID INT IDENTITY, NAME NVARCHAR(20),PRICE MONEY)
    INSERT INTO @T (NAME,PRICE) VALUES ('PRODUCT 1',100)
    INSERT INTO @T (NAME,PRICE) VALUES ('PRODUCT 2',220)
    INSERT INTO @T (NAME,PRICE) VALUES ('PRODUCT 3',70)
    
    DECLARE @C TABLE (ID INT IDENTITY, NAME NVARCHAR(20), VALUE INT, IS_PERCENT BIT)
    INSERT INTO @C (NAME,VALUE,IS_PERCENT) VALUES ('COUPON 1 : -15$',15,0)
    INSERT INTO @C (NAME,VALUE,IS_PERCENT) VALUES ('COUPON 2 : -5$',5,0)
    INSERT INTO @C (NAME,VALUE,IS_PERCENT) VALUES ('COUPON 3 : -10%',10,1)
    INSERT INTO @C (NAME,VALUE,IS_PERCENT) VALUES ('COUPON 4 : -12$',12,0)
    
    ;WITH MIX AS (
    	SELECT	ID,NAME,PRICE,DISCOUNT_PRICE = PRICE,COUPONS_APPLIED = 0,COUPON_NAMES = CAST('' AS NVARCHAR(40)),COUPON_ID = 0
    	FROM	@T T
    	UNION ALL 
    	SELECT	MIX.ID,MIX.NAME,PRICE,DISCOUNT_PRICE = 
    			CASE WHEN IS_PERCENT = 1 THEN DISCOUNT_PRICE * (100-C.VALUE) /100 ELSE DISCOUNT_PRICE - C.VALUE END
    			,COUPONS_APPLIED = COUPONS_APPLIED +1
    			,COUPON_NAMES = CAST(COUPON_NAMES + ' + ' + C.NAME AS NVARCHAR(40))
    			,COUPON_ID = C.ID
    	FROM	MIX,@C C
    	WHERE	1=1
    		AND	COUPONS_APPLIED < 2
    		AND COUPON_ID <> C.ID
    )
    SELECT ID,NAME,PRICE,DISCOUNT_PRICE,COUPON_NAMES
    FROM (
    	SELECT	A.ID,A.NAME,A.PRICE,A.DISCOUNT_PRICE
    			,COUPON_NAMES =SUBSTRING(A.COUPON_NAMES,3,LEN(A.COUPON_NAMES))
    			,NB = ROW_NUMBER() OVER (PARTITION BY A.ID ORDER BY A.DISCOUNT_PRICE )
    	FROM	MIX A
    		INNER JOIN 
    			(
    			SELECT ID,MIN(DISCOUNT_PRICE) AS DISCOUNT_PRICE
    			FROM MIX
    			WHERE 1=1
    				AND DISCOUNT_PRICE >= PRICE * 0.60
    			GROUP BY ID
    			) B ON A.ID = B.ID
    	WHERE A.DISCOUNT_PRICE = B.DISCOUNT_PRICE
    	) A
    WHERE NB = 1
    ORDER BY A.ID
    

    Encore une fois nous voyons l'intéret des CTE sur ce genre de requête.

    Quelques points à noter:

    Comme je le disais j'attache beaucoup d'importante à l'écriture et la lisibilité des requêtes car je trouve que c'est un point toujours beaucoup trop négligé. Combien de fois arrivez vous sur du code de quelqu'un d'autre sans comprendre ce qu'il fait même avec une lecture approfondie? C'est un vieil adage d'autant plus vrai en sql...

    L'avantage de la solution proposée ici est que dans un contexte applicatif réel, je peux sortir facilement sous forme de variable le taux maximum de discount ainsi que le nombre de coupons appliqués (contrairement à des solutions avec une requête par coupon). De plus la séparation des actions se fait en plusieurs étapes et l'on peu donc faire évoluer le modèle simplement.

    J'ai quand même pris le temps de profiler les différentes requêtes, et le fait est que la solution Sql sans CTE est moins souple mais comme on pouvait s'y attendre plus performante. Donc si vous êtes dans un cas à périmètre clairement défini et que les performances sont importantes, faites attention aux CTE qui sont souvent couteuses (mais parfois aussi font gagner du temps...).

    Un petit piège pas méchant s'était glissé dans le challenge, le fait d'ajouter les noms des coupons utlisés. En effet lors de l'uilisation des CTE il faut faire attention aux types des champs de la première requête. Si vous ne faites pas un cast sur le champ d'origine pour prendre en compte les caractère concaténés dans le futur vous autres un problème de tronquage ou de cast. Il faut anticiper ses besoins et c'est le pourquoi du COUPON_NAMES = CAST('' AS NVARCHAR(40)) dans la première partie du CTE.

     

    En cadeau aux lecteurs et participants, un bon livre assez rare sur Sql Server profiler que je ne saurait que vous conseiller si vous avez un couple d'heures à perdre:

    2852

    (merci à Red-Gate pour sponsoriser cette publication et sa mise à disposition gratuite!)

    Merci à tous et à bientot pour le prochain challenge.


    Classé sous , , , ,

    ASP.NET MVC: Sources et Licence

    Les sources d'ASP.NET MVC V1.0 étaient déjà disponibles depuis quelques jours suite au mix, mais la dernière annonce de Scott Guthrie vaut quand même qu'on s'y attarde un peu et qu'on la relaie.

    Ces sources viennent d'être rendues disponibles sous licence MS-PL (Microsoft Public Licence). C'est une vraie licence open-source approuvée par l'OSI. Ce n'est pas le seul produit de chez Microsoft à être régit par cette licence mais c'est peut-être le framework le plus important qu'ils nous livrent sous cette licence. Pour rappel MEF, DLR et IronRuby, Ajax Control Toolkit ou encore le Silverlight Toolkit sont aussi sous cette licence.

    Cette licence permet donc d'utiliser le produit librement mais aussi de le changer, de distribuer ses changements et éventuellement de maintenir une version divergeante!

    Je ne pense pas que ce soit un mouvement de fond et que Microsoft se convertisse au tout open-source du jour au lendemain, néanmoins ce projet à eut depuis ses débuts un parcours très atypique chez Microsoft. Il n'y a pas eut moins de 10 versions livrés aux tests du public entre octobre 2007 et la release finale de mars 2009. Mais c'est peut-être aussi ce qui a permis une telle adhésion de toute une catégorie de développeurs et une maturité certaine dans un produit estampillé 1.0.

    Pour le coup, merci ;-)

    Encore une fois, pour le téléchargement des sources, c'est sur CodePlex que ça se passe:
    http://aspnet.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=24471


    Classé sous , , ,

    SSMS: Erreur 0x80004002 après install IE8

    Je ne sais pas quelle est exactement la portée de ce problème, néanmoins, si vous vous trouvez sur un Windows Server 2008 x64 avec Sql Server Management Studio 2008 d'installé, lors de l'installation d'IE8, vous aurez peut-être quelques surprises.

    Le problème rencontré (et pas qu'à moi ;-)), est le suivant: lors l'ouverture d'une base dans SSMS dans l'explorateur d'objets, une vilaine erreur com nous tombe dessus:

    SSMS - Unable to cast COM object of type 'System.__ComObject' to interface type 'Microsoft.VisualStudio.OLE.Interop.IServiceProvider'. This operation failed because the QueryInterface call on the COM component for the interface with IID '{6D5140C1-7436-11CE-8034-00AA006009FA}' failed due to the following error: No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE)). (Microsoft.VisualStudio.OLE.Interop)



    En bref, SSMS devient inutilisable pour des tâches courantes et vous permet tout juste d'exécuter vos scripts.

    Ce problème intervient aussi sous Visual Studio 2008, et ce de manière beaucoup plus sournoise puisque Visual Studio crashe sans autre forme. Cela arrive lorsque vous voulez afficher le contenu d'une table par le biais du Server Explorer.

    Il s'agit à priori de références qui ont sauté dans la base de registres lors de l'installation d'IE8. Pour résoudre cela, le plus simple est de ré-enregistrer la dll suivante en ouvrant une console en mode Admin:

    regsvr32 actxprxy.dll

    Après cela vous retrouverez un Visual Studio 2008 et un SSMS 2008 fonctionnels...


    Classé sous , ,

    SQL : Challenge #03

    J’ai commencé cette série il y a quelques semaines en me basant sur les challenges de l’excellent Jacob Sebastian (challenge #1, challenge #2 & challenge #3).

    J’ai trouvé que c’était réellement un bon exercice de style et qui plus est fun (pas forcément pour tout le monde je vous l’accorde). Je pense que c’est un bon moyen de réfléchir sur des problèmes courants, de voir les différentes solutions possibles mais aussi de mettre en avant certaines techniques et d’apprendre ou de revoir certains points particuliers du sql qui sont peut-être moins connus.

    En bref, c’est un bon moyen de se perfectionner en sql par la pratique en échangeant des solutions, des points de vues et en s’amusant.

    C’est pourquoi je vais ajouter mes propres challenges dont voici le premier.

     

    Le Contexte

    Nous avons une table de produits avec leurs prix:

    ID          NAME                             PRICE
    ----------- -------------------------------- ---------------------
    1           PRODUCT 1                        100,00
    2           PRODUCT 2                        220,00
    3           PRODUCT 3                        70,00

    Et une table contenant des bons de réduction:

    ID          NAME                             VALUE       IS_PERCENT
    ----------- -------------------------------- ----------- ----------
    1           COUPON 1 : -15$                  15          0
    2           COUPON 2 : -5$                   5           0
    3           COUPON 3 : -10%                  10          1
    4           COUPON 4 : -12$                  12          0

     

    Un ou deux bons peuvent être utilisés pour chaque produit mais le prix final réduit ne doit pas être inférieur à 60% du prix initial.

    Le Challenge

    Le but est ici de trouver pour chaque produit le prix minimum pouvant être payé en utilisant n’importe quelle combinaison de bons de réduction et en tenant compte des restrictions ci-dessus. Il faudra aussi produire une description des bons de réduction appliqués.

    Voici la table finale résultante de vos calculs que vous devrez produire:

    ID          NAME                 PRICE                 DISCOUNT_PRICE        COUPON_NAMES
    ----------- -------------------- --------------------- --------------------- ----------------------------------------
    1           PRODUCT 1            100,00                73,00                  COUPON 1 : -15$ + COUPON 4 : -12$
    2           PRODUCT 2            220,00                183,00                 COUPON 3 : -10% + COUPON 1 : -15$
    3           PRODUCT 3            70,00                 43,00                  COUPON 1 : -15$ + COUPON 4 : -12$

     

    Notes

    • Le challenge doit être fait en une seule requête sql (sans tables temporaires, variable,etc…)
    • Il n’y a pas de restrictions de version de sql serveur, toutes les techniques à votre disposition peuvent être utilisées (dans la mesure où les contraintes du challenge sont respectées et que cela est fait en une requête)
    • Vos réponses doivent impérativement utiliser le jeux de données fournis (sans quoi il sera difficile pour moi de tester)
    • Les réponses sont à m’envoyer par mail sur [challenge at rui point fr]
    • Date limite d’envoi: le 3 avril 2009.

     

    Données à utiliser:

    DECLARE @T TABLE (ID INT IDENTITY, NAME NVARCHAR(20),PRICE MONEY)
    INSERT INTO @T (NAME,PRICE) VALUES ('PRODUCT 1',100)
    INSERT INTO @T (NAME,PRICE) VALUES ('PRODUCT 2',220)
    INSERT INTO @T (NAME,PRICE) VALUES ('PRODUCT 3',70)
    
    DECLARE @C TABLE (ID INT IDENTITY, NAME NVARCHAR(20), VALUE INT, IS_PERCENT BIT)
    INSERT INTO @C (NAME,VALUE,IS_PERCENT) VALUES ('COUPON 1 : -15$',15,0)
    INSERT INTO @C (NAME,VALUE,IS_PERCENT) VALUES ('COUPON 2 : -5$',5,0)
    INSERT INTO @C (NAME,VALUE,IS_PERCENT) VALUES ('COUPON 3 : -10%',10,1)
    INSERT INTO @C (NAME,VALUE,IS_PERCENT) VALUES ('COUPON 4 : -12$',12,0)

    Je publierai les résultat quelques jours après cette date.

    Have fun!


    Classé sous , , , ,

    SQL: réponses au challenges #2

    Voici donc les réponses au challenge #2 pour lequel j’ai eu un peu plus de participants que la dernière fois et je vous en remercie tous, ces échanges étaient vraiment très sympathiques.

    Un grand bravo à Nicolas et Antoine pour avoir proposé des bonnes solutions

    Pour rappel, le sujet était de déterminer sur une plage de dates, le nombre d’heures de travail. Le sujet complet se trouve sur le premier post ici.

    La difficulté ici était bien sur de pouvoir gérer une plage de dates entre celles de début et de fin. Tout autre mode calculatoire est à proscrire dans ce cas car cela engendrerai des calculs trop compliqués et non fiables.

    Si la problématique n’avait pas été de faire tout cela en une requête cela aurait été relativement simple car il aurait suffit de créer une table temporaire que l’on aurait rempli par le biais d’une boucle pour chaque date de début et de fin. C’est toujours un exemple intéressant pour montrer comment faire des boucles toutes simples sans vilains curseurs:

    DECLARE @D TABLE (ID INT,Date DATETIME)
    DECLARE @ID INT, @FROM DATETIME, @TO DATETIME
    SET @ID = 0
    
    SELECT TOP 1 @ID = ID FROM @t WHERE ID > @ID
    WHILE @@ROWCOUNT > 0
    BEGIN
    	SELECT @FROM = StartDate, @TO = EndDate FROM @t WHERE ID = @ID
    	
    	WHILE @FROM < @TO
    	BEGIN
    		INSERT INTO @D
    		SELECT @ID,@FROM
    		
    		SELECT @FROM = DATEADD(DAY,1,@FROM)	
    	END
    	INSERT INTO @D SELECT @ID,@TO
    	SELECT TOP 1 @ID = ID FROM @t WHERE ID > @ID
    END
    
    SELECT * FROM @D

    Evidemment si ont part sur le principe qu’il faut tout faire en une seule requête la problématique est tout autre. Pour cela la meilleure solution reste d’utiliser les CTE qui même si elles sont plutôt faites pour créer des structures hiérarchiques peuvent très bien convenir pour de simples itérations.

    Voici donc la solution que je vous propose:

    DECLARE @t TABLE (ID INT IDENTITY, StartDate DATETIME, EndDate DATETIME)
    SET DATEFORMAT MDY
    SET DATEFIRST 1
    
    INSERT INTO @t (StartDate, EndDate) SELECT '3/2/2009 8:00AM', '3/2/2009 3:00PM' --07:00
    INSERT INTO @t (StartDate, EndDate) SELECT '3/1/2009 4:00PM', '3/3/2009 2:00 PM' --15:00
    INSERT INTO @t (StartDate, EndDate) SELECT '2/26/2009 7:00AM', '2/26/2009 10:00PM' --09:00
    INSERT INTO @t (StartDate, EndDate) SELECT '1/27/2009 9:15 AM', '1/27/2009 5:15 PM' --07:45
    INSERT INTO @t (StartDate, EndDate) SELECT '1/17/2009 1:45 PM', '1/19/2009 7:45 AM' --00:00
    INSERT INTO @t (StartDate, EndDate) SELECT '1/27/2009 9:15 PM', '1/28/2009 9:15 AM' --01:15
    -- Add this other values to test weekends and invalid values
    INSERT INTO @t (StartDate, EndDate) SELECT '3/7/2009 18:00PM', '3/17/2009 8:15AM' --54:15
    INSERT INTO @t (StartDate, EndDate) SELECT '3/5/2009 18:00PM', '3/10/2009 7:00AM' --18:00
    INSERT INTO @t (StartDate, EndDate) SELECT '1/27/2009 16:15 PM', '1/27/2009 9:15 AM' --0 
    
    -- Build the range of days between start and end with additional helper calcultations
    ;WITH BUILD_RANGES AS
    (
    		-- select the exact start date based on business hours
    		SELECT	T.ID
    				,StartDate = 
    						CASE 
    						WHEN DATEPART(HOUR,T.StartDate) < 8 THEN DATEADD(HOUR,8,DATEADD(DAY,0,DATEDIFF(DAY,0,T.StartDate))) 
    						WHEN DATEPART(HOUR,T.StartDate) > 17 THEN DATEADD(HOUR,17,DATEADD(DAY,0,DATEDIFF(DAY,0,T.StartDate))) 
    						ELSE T.StartDate 
    						END
    				,T.EndDate 
    				,BusinessDay = CASE WHEN DATEPART(DW,T.StartDate) IN (6,7) OR T.EndDate < T.StartDate THEN 0 ELSE 1 END 
    		FROM @t T
    		UNION ALL
    		-- Select the other dates til the end
    		SELECT	A.ID
    				,StartDate = DATEADD(HOUR,8,DateAdd(day,1,DATEADD(DAY,0,DATEDIFF(DAY,0,A.StartDate))))
    				,A.EndDate
    				,BusinessDay = CASE WHEN DATEPART(DW,DateAdd(day,1,A.StartDate)) IN (6,7) THEN 0 ELSE 1 END 
    		FROM BUILD_RANGES A
    			INNER JOIN @t T ON A.ID = T.id
    		WHERE A.StartDate < T.EndDate
    )
    -- do final computation
    SELECT	ID,StartDate,EndDate,
    		HOURS = SUM(DATEDIFF(MINUTE,ComputedStart,ComputedEnd))/60,
    		MINUTES = SUM(DATEDIFF(MINUTE,ComputedStart,ComputedEnd))%60
    FROM	(
    	-- select final values with enddate based on business hours
    	SELECT  O.Id
    			,ComputedStart = C.StartDate
    			,ComputedEnd = 
    						CASE WHEN DATEADD(DAY,0,DATEDIFF(DAY,0,C.StartDate)) = DATEADD(DAY,0,DATEDIFF(DAY,0,O.EndDate))
    						THEN 
    							CASE 
    							WHEN DATEPART(HOUR,C.EndDate) < 8 THEN DATEADD(HOUR,8,DATEADD(DAY,0,DATEDIFF(DAY,0,C.EndDate))) 
    							WHEN DATEPART(HOUR,C.EndDate) > 16 THEN DATEADD(HOUR,17,DATEADD(DAY,0,DATEDIFF(DAY,0,C.EndDate))) 
    							ELSE CASE WHEN O.StartDate > O.EndDate THEN C.StartDate ELSE C.EndDate END
    							END
    						ELSE
    							DATEADD(HOUR,17,DATEADD(DAY,0,DATEDIFF(DAY,0,C.StartDate)))
    						END
    			,BusinessDay
    			,O.StartDate,O.EndDate
    	FROM	BUILD_RANGES C
    		FULL JOIN @t O ON C.ID = O.ID
    ) FINAL_DATA
    WHERE 1=1
    	AND	(BusinessDay = 1 OR StartDate > EndDate)
    	AND DATEADD(DAY,0,DATEDIFF(DAY,0,ComputedStart)) <= DATEADD(DAY,0,DATEDIFF(DAY,0,EndDate))
    GROUP BY ID,StartDate,EndDate
    ORDER BY ID
    GO

    Les points d’intérêt:

    La CTE

    Nous faisons un union entre notre table de départ et le résultat de la requête lui-même de manière récursive en ajoutant 1 jour à chaque fois à la StartDate. On s’arrête avant le EndDate.

    Récupérer le jour d’une date

    cela n’a l’air de rien, mais vous ne pouvez pas simplement extraire d’une date (jour+heures) le jour sans les informations de temps! La solution la plus simple et la plus efficace est d’ajouter les jours de la date à la date 0:

    DATEADD(DAY,0,DATEDIFF(DAY,0,C.StartDate))

    Cette méthode est très pratique et efficace, vous pouvez la réutiliser pour tout autre type de calcul du même genre (calcul d’heure, calcul du premier jour de la semaine,etc…)

    A bientôt pour un prochain challenge!


    Classé sous ,

    IE8: forcer le mode de compatibilité

    IE8 est disponible en téléchargement depuis hier en version finale.

    C'est surement une grande nouvelle pour la plupart des gens mais aussi potentiellement une source de problèmes pour les développeurs web. Même si les poliques de masterisations des postes dans les grands groupes permettent de définir une plateforme stable et qui ne va pas se mettre à jour sur IE8 tout de suite (votre application intranet se sera pas cassée tout de suite donc), il n'en est pas de même pour les petites entreprises ou les particuliers qui vont très certainement et massivement passer sur IE8 par Windows Update.

    Donc, après avoir passé des mois à pauffiner votre site pour IE7/Firefox et bataillé pour limiter la casse sur IE6, IE8 arrive et tout est à refaire car le moteur de rendu de ce dernier a complement changé par rapport à IE7. En attendant de faire les mises à jour nécessaires, vous pouvez forcer le mode de compatibilité d'IE8 en IE7 par le meta suivant:

        <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
      
    Cela devrait vous laisser le temps de souffler un peu ;-).

    Je vous redonne juste l'adresse de téléchargement au cas improbable ou vous l'ayez manqué:
    http://www.microsoft.com/windows/internet-explorer/

    Ainsi que la doc développeur IE8:
    http://download.microsoft.com/download/9/6/6/96619F43-2247-4E82-92BC-89D9F503FA2B/Windows%20Internet%20Explorer%208%20Technology%20Overview%20for%20Developers.pdf

    Et que le post que j'avais fait il y a quelques mois sur l'ajout d'une Activity IE8 pour pouvoir rechercher sur un site en particulier (le votre par exemple) directement à partir de la barre de recherche:
    http://www.rui.fr/2008/03/17/IE8ActivitiesRechercheSurUnSite.aspx

    Bon Surf!


    Classé sous , , ,
    Plus de Messages Page suivante »

    Les 10 derniers blogs postés

    - [Refactoring] ReSharper pour Visual Studio 2010 (Preview) par Thomas Jaskula le il y a 2 heures et 27 minutes

    - [Refactoring] Analyser vos exceptions avec ReSharper Exceptional par Thomas Jaskula le il y a 3 heures et 41 minutes

    - SharePoint 2007 : patterns & practices SharePoint Guidance par Philippe Sentenac [MVP SharePoint] le il y a 17 heures et 21 minutes

    - [Visual Studio 2010] Les tests cases c’est bien, mais je vais devoir tout réécrire ? par Etienne Margraff le il y a 18 heures et 17 minutes

    - MVP[Gribouillon].AddYear par The Grib's Lair [Sébastien PICAMELOT - MVP SharePoint] le il y a 18 heures et 32 minutes

    - Clinique INSIA - Projet de fin d’Etudes (Silverlight 3 MVVM et OutOfBrowser, WCF, TFS) - Part 1 par David REI le 07-02-2009, 23:38

    - C’est la crise ? Bah pourquoi cramer du budget pub alors ? par Nix's Blog le 07-02-2009, 15:31

    - Soyons MVP ! par TheSaib .NET blog le 07-02-2009, 12:15

    - SharePoint : Gestion des Erreurs 6398, 7076 et 6482 par Blog Technique de Romelard Fabrice le 07-02-2009, 11:53

    - EF avec WPF par Matthieu MEZIL le 07-02-2009, 10:18