Advertisement
Guest User

Daniels bidrag till SQLUG Challenge 2017

a guest
Mar 22nd, 2017
42
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
T-SQL 3.60 KB | None | 0 0
  1. --- En dummy-tabell med clustered columnstore index.
  2. --- Jag gör LEFT JOIN #ColStoreTable ON 1=0 på flera ställen för
  3. --- att få till s.k. batch mode processing.
  4. ---
  5. --- http://sqlmag.com/sql-server/what-you-need-know-about-batch-mode-window-aggregate-operator-sql-server-2016-part-1
  6. ---
  7. CREATE TABLE #ColStoreTable (
  8.     col     tinyint NOT NULL
  9. );
  10. CREATE CLUSTERED COLUMNSTORE INDEX ColStoreIndex ON #ColStoreTable;
  11. INSERT INTO #ColStoreTable VALUES (0);
  12. ALTER INDEX ColStoreIndex ON #ColStoreTable REORGANIZE;
  13.  
  14.  
  15.  
  16. BEGIN TRANSACTION;
  17.  
  18.     TRUNCATE TABLE dbo.Customers;
  19.  
  20.  
  21.     --- Steg 1 av 2:
  22.     WITH mappings AS (
  23.         SELECT ISNULL(b._from, a.PurchaseID) AS _from, MIN(c._to) AS _to
  24.         FROM (
  25.  
  26.             --- För varje inköp, hitta det lägsta PurchaseID som har samma kombination av
  27.             --- (förnamn, mail), (förnamn, adress) respektive (förnamn, kreditkort).
  28.             SELECT p.PurchaseID,
  29.                    MIN(p.PurchaseID) OVER (PARTITION BY p.FirstName, p.Email) AS _mailID,
  30.                    MIN(p.PurchaseID) OVER (PARTITION BY p.FirstName, p.LastName, p.StreetAddress, p.ZipCode) AS _addrID,
  31.                    MIN(p.PurchaseID) OVER (PARTITION BY p.FirstName, p.CreditCard) AS _ccID
  32.             FROM dbo.Purchases AS p
  33.             LEFT JOIN #ColStoreTable AS x ON 1=0
  34.             ) AS a
  35.         OUTER APPLY (
  36.  
  37.             --- "Unpivot"era dessa fyra värden:
  38.             SELECT _from FROM (
  39.                 VALUES
  40.                     (a._mailID),
  41.                     (a._addrID),
  42.                     (a._ccID),
  43.                     (a.PurchaseID)
  44.                 ) AS sub(_from)
  45.             WHERE _include=1) AS b
  46.         OUTER APPLY (
  47.  
  48.             --- Ta fram det lägsta av (_mailID, _addrID och _ccID)
  49.             VALUES ((CASE
  50.                 WHEN a._ccID  <=a._mailID AND a._ccID  <=a._addrID THEN a._ccID
  51.                 WHEN a._mailID<=a._ccID   AND a._mailID<=a._addrID THEN a._mailID
  52.                 WHEN a._addrID<=a._mailID AND a._addrID<=a._ccID   THEN a._addrID END))
  53.             ) AS c(_to)
  54.  
  55.         --- DISTINCT'a utdatan för att eliminera dubletter som uppstår:
  56.         GROUP BY ISNULL(b._from, a.PurchaseID)
  57.         )
  58.  
  59.     --- Dumpa ut allting till dbo.Customers.
  60.     INSERT INTO dbo.Customers WITH (TABLOCKX, HOLDLOCK) (PurchaseID, CustomerID)
  61.     SELECT _from AS PurchaseID, _to AS CustomerID
  62.     FROM mappings;
  63.  
  64.  
  65.  
  66.     --- I dbo.Customers ligger det nu i princip en parent-child-struktur
  67.     --- där en parent (CustomerID) kan ha flera children (PurchaseID). Det vi
  68.     --- vill göra nu är att alla parents ska ligga på "toppnivån".
  69.  
  70.  
  71.  
  72.     --- Steg 2 av 2:
  73.     --- Rekursiv CTE som mappar alla relationer vidare "uppåt" i hierarkin:
  74.     WITH cte AS (
  75.         --- Utgå från de relationer som antas vara toppnoder just nu
  76.         --- (PurchaseID=CustomerID).
  77.         SELECT PurchaseID, CustomerID
  78.         FROM dbo.Customers WITH (TABLOCKX, HOLDLOCK)
  79.         WHERE PurchaseID=CustomerID
  80.  
  81.         UNION ALL
  82.  
  83.         --- Mappa dem till en ny parent-nod.
  84.         SELECT p.PurchaseID, cte.CustomerID
  85.         FROM cte
  86.         INNER JOIN dbo.Customers AS p WITH (TABLOCKX, HOLDLOCK) ON
  87.             p.PurchaseID>cte.PurchaseID AND
  88.             p.CustomerID=cte.PurchaseID AND
  89.             p.CustomerID!=p.PurchaseID)
  90.  
  91.     --- Uppdatera tillbaka till dbo.Customers i förekommande fall.
  92.     --- Tvingar en HASH join för att bättra på prestanda med batch mode-processning
  93.     --- och sätter MAXRECURSION till 0 ifall någon relation har mer än 100 nivåer (köp)
  94.     --- till toppnoden.
  95.     UPDATE c
  96.     SET c.CustomerID=cte.CustomerID
  97.     FROM dbo.Customers AS c WITH (TABLOCKX, HOLDLOCK)
  98.     INNER HASH JOIN cte ON
  99.         cte.PurchaseID!=cte.CustomerID
  100.         AND c.PurchaseID=cte.PurchaseID
  101.     LEFT JOIN #ColStoreTable AS cs ON 1=0
  102.     WHERE c.CustomerID!=cte.CustomerID
  103.     OPTION (MAXRECURSION 0);
  104.  
  105. --- Vild chansning: Om DELAYED_DURABILITY är påslagen för databasen så gör
  106. --- vi det bästa av det här:
  107. COMMIT TRANSACTION WITH (DELAYED_DURABILITY=ON);
  108.  
  109. DROP TABLE #ColStoreTable;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement