SlideShare ist ein Scribd-Unternehmen logo
1 von 31
Downloaden Sie, um offline zu lesen
loan_nbr   customer_nbr   code     value
                  1          1              amount   1500.00
                  1          1              date     20080110
                  1          1              type     personal
                  2          2              amount   3500.00
                  2          2              date     20080215
                  2          2              type     personal




CREATE TABLE EAV_Loans (
 loan_nbr INT NOT NULL,
 customer_nbr INT NOT NULL,
 code VARCHAR(30) NOT NULL,
 value VARCHAR(200),
 CONSTRAINT pk_eav_loans
 PRIMARY KEY (loan_nbr, customer_nbr, code));
-- Customers with personal loans over 1000.00 for the period
-- Jan 1, 2008 through Jan 31, 2008

SELECT A.loan_nbr,
       A.customer_nbr,
       CAST(A.value AS DATETIME) AS loan_date,
       CAST(B.value AS DECIMAL(15, 2)) AS loan_amount
FROM EAV_Loans AS A
INNER JOIN EAV_Loans AS B
   ON A.loan_nbr = B.loan_nbr
  AND A.customer_nbr = B.customer_nbr
INNER JOIN EAV_Loans AS C
   ON A.loan_nbr = C.loan_nbr
  AND A.customer_nbr = C.customer_nbr
WHERE A.code = 'date'
  AND CAST(A.value AS DATETIME) >= '20080101'
  AND CAST(A.value AS DATETIME) < '20080201'
  AND B.code = 'amount'
  AND CAST(B.value AS DECIMAL(15, 2)) > 1000.00
  AND C.code = 'type'
  AND C.value = 'personal';
SELECT A.loan_nbr,
       A.customer_nbr,
       loan_date,
       loan_amount
FROM (SELECT loan_nbr, customer_nbr,
             CAST(value AS DATETIME) AS loan_date
      FROM EAV_Loans
      WHERE code = 'date') AS A
INNER JOIN (SELECT loan_nbr, customer_nbr,
                   CAST(value AS DECIMAL(15, 2))
                              AS loan_amount
            FROM EAV_Loans
            WHERE code = 'amount') AS B
   ON A.loan_nbr = B.loan_nbr
  AND A.customer_nbr = B.customer_nbr
INNER JOIN (SELECT loan_nbr, customer_nbr,
                   value AS loan_type
            FROM EAV_Loans
            WHERE code = 'type') AS C
   ON A.loan_nbr = C.loan_nbr
  AND A.customer_nbr = C.customer_nbr
WHERE loan_date >= '20080101'
  AND loan_date < '20080201'
  AND loan_amount > 1000.00
  AND loan_type = 'personal';
SELECT loan_nbr,
        customer_nbr,
        loan_date,
        loan_amount
FROM (SELECT loan_nbr,
              customer_nbr,
              MAX(CASE WHEN code = 'date'
                       THEN CAST(value AS DATETIME) END),
              MAX(CASE WHEN code = 'amount'
                       THEN CAST(value AS DECIMAL(15, 2)) END),
              MAX(CASE WHEN code = 'type'
                       THEN value END)
      FROM EAV_Loans
      GROUP BY loan_nbr, customer_nbr
      )
   AS L(loan_nbr, customer_nbr, loan_date, loan_amount, loan_type)
WHERE loan_date >= '20080101'
  AND loan_date < '20080201'
  AND loan_amount > 1000.00
  AND loan_type = 'personal';
loan_nbr   customer_nbr   loan_date                 loan_amount   loan_type
1          1              2008-01-10 00:00:00.000   1500.00       personal
2          2              2008-02-15 00:00:00.000   3500.00       personal




CREATE TABLE Loans (
 loan_nbr INT NOT NULL,
 customer_nbr INT NOT NULL,
 loan_date DATETIME NOT NULL,
 loan_amount DECIMAL(15, 2) NOT NULL,
 loan_type VARCHAR(10) NOT NULL,
 CONSTRAINT ck_loan_type
 CHECK (loan_type IN ('personal', 'business')),
 CONSTRAINT pk_loans
 PRIMARY KEY (loan_nbr));
-- Convert EAV table to normalized
INSERT INTO Loans
(loan_nbr, customer_nbr, loan_date, loan_amount, loan_type)
SELECT loan_nbr,
       customer_nbr,
       MAX(CASE WHEN code = 'date'
                THEN CAST(value AS DATETIME) END),
       MAX(CASE WHEN code = 'amount'
                THEN CAST(value AS DECIMAL(15, 2)) END),
       MAX(CASE WHEN code = 'type' THEN value END)
FROM EAV_Loans
GROUP BY loan_nbr, customer_nbr;
-- Customers with personal loans over 1000.00
-- for period Jan 1, 2008 through Jan 31, 2008
SELECT loan_nbr, customer_nbr, loan_date, loan_amount
FROM Loans
WHERE loan_date >= '20080101'
  AND loan_date < '20080201'
  AND loan_amount > 1000.00
  AND loan_type = 'personal';
-- Replacement view for legacy code
CREATE VIEW EAV_Loans
(loan_nbr, customer_nbr, code, value)
AS
SELECT loan_nbr, customer_nbr,
       CAST('date' AS VARCHAR(30)),
       CONVERT(VARCHAR(200), loan_date, 112)
FROM Loans
UNION
SELECT loan_nbr, customer_nbr,
       CAST('amount' AS VARCHAR(30)),
       CAST(loan_amount AS VARCHAR(200))
FROM Loans
UNION
SELECT loan_nbr, customer_nbr,
       CAST('type' AS VARCHAR(30)),
       CAST(loan_type AS VARCHAR(200))
FROM Loans;
loan_nbr   loan_date                 loan_amount   loan_type   rk
3          2008-03-11 00:00:00.000   5000.00       business    1
6          2008-03-27 00:00:00.000   4000.00       business    2
7          2008-04-10 00:00:00.000   3500.00       business    3
4          2008-03-12 00:00:00.000   2000.00       personal    1
8          2008-04-12 00:00:00.000   2000.00       personal    2
1          2008-01-01 00:00:00.000   1500.00       personal    3
5          2008-03-25 00:00:00.000   1200.00       personal    4
2          2008-02-15 00:00:00.000   1000.00       personal    5
SELECT loan_nbr, loan_date, loan_amount,
       loan_type,
      (SELECT COUNT(*)
       FROM Loans AS L2
       WHERE L2.loan_type = L1.loan_type
         AND (L2.loan_amount > L1.loan_amount
          OR L2.loan_amount = L1.loan_amount
         AND L2.loan_nbr <= L1.loan_nbr)) AS rk
FROM Loans AS L1
ORDER BY loan_type, rk;
SELECT loan_nbr, loan_date, loan_amount, loan_type,
       ROW_NUMBER() OVER(PARTITION BY loan_type
                         ORDER BY loan_amount DESC,
                                  loan_nbr) AS rk
FROM Loans
ORDER BY loan_type, rk;
loan_nbr   customer_nbr       loan_date                 loan_amount    loan_type
2          2                  2008-02-15 00:00:00.000   1000.00        personal
3          1                  2008-03-11 00:00:00.000   4500.00        business
4          3                  2008-03-12 00:00:00.000   2000.00        personal




               loan_nbr   customer_nbr    loan_date                   loan_amount   loan_type
               1          1               2008-01-01 00:00:00.000     1500.00       personal
               2          2               2008-02-15 00:00:00.000     1000.00       personal
               3          1               2008-03-11 00:00:00.000     5000.00       business




loan_nbr   customer_nbr       loan_date                 loan_amount    loan_type
2          2                  2008-02-15 00:00:00.000   1000.00        personal
3          1                  2008-03-11 00:00:00.000   4500.00        business
4          3                  2008-03-12 00:00:00.000   2000.00        personal
-- Update changed
UPDATE Loans
SET loan_amount = (SELECT D.loan_amount
                   FROM DailyChangedLoans AS D
                   WHERE D.loan_nbr = Loans.loan_nbr
                     AND D.loan_amount <> Loans.loan_amount)
WHERE EXISTS(SELECT *
             FROM DailyChangedLoans AS D
             WHERE D.loan_nbr = Loans.loan_nbr
               AND D.loan_amount <> Loans.loan_amount);

-- Insert new loans
INSERT INTO Loans
(loan_nbr, customer_nbr, loan_date, loan_amount, loan_type)
SELECT loan_nbr,
       customer_nbr,
       loan_date,
       loan_amount,
       loan_type
FROM DailyChangedLoans AS D
WHERE NOT EXISTS(SELECT *
                 FROM Loans AS L
                 WHERE D.loan_nbr = L.loan_nbr);

-- Remove deleted
DELETE FROM Loans
WHERE NOT EXISTS(SELECT *
                 FROM DailyChangedLoans AS D
                 WHERE D.loan_nbr = Loans.loan_nbr);
-- Using a single MERGE statement
MERGE INTO Loans AS L
USING DailyChangedLoans AS D
   ON D.loan_nbr = L.loan_nbr
WHEN MATCHED
 AND L.loan_amount <> D.loan_amount
THEN UPDATE SET loan_amount = D.loan_amount
WHEN NOT MATCHED
THEN INSERT VALUES(D.loan_nbr,
                   D.customer_nbr,
                   D.loan_date,
                   D.loan_amount,
                   D.loan_type)
WHEN NOT MATCHED BY SOURCE
THEN DELETE;
loan_nbr   customer_nbr   loan_date                  loan_amount   loan_type
1          1              2008-01-01 00:00:00.000    1500.00       personal
2          2              2008-01-02 00:00:00.000    1000.00       personal
3          1              2008-01-03 00:00:00.000    5000.00       business
4          3              2008-01-12 00:00:00.000    2000.00       personal
5          4              2008-01-13 00:00:00.000    1200.00       personal
6          3              2008-01-29 00:00:00.000    4000.00       business
7          5              2008-01-30 00:00:00.000    3500.00       business
8          2              2008-01-31 00:00:00.000    2000.00       personal




                           start_date                 end_date
                           2008-01-01 00:00:00.000    2008-01-03 00:00:00.000
                           2008-01-12 00:00:00.000    2008-01-13 00:00:00.000
                           2008-01-29 00:00:00.000    2008-01-31 00:00:00.000
-- Find last date for date range
-- and use as grouping factor

SELECT MIN(loan_date) AS start_date,
       MAX(loan_date) AS end_date
FROM (SELECT loan_date,
            (SELECT MIN(L2.loan_date)
             FROM Loans AS L2
             WHERE L2.loan_date >= L1.loan_date
               AND NOT EXISTS
                  (SELECT *
                   FROM Loans AS L3
                   WHERE L3.loan_date =
                         DATEADD(DAY, 1, L2.loan_date))
             ) AS base
      FROM Loans AS L1) AS L
GROUP BY base;
-- Preparation for solution
SELECT loan_date,
       DATEDIFF(DAY, '19000101', loan_date) AS days_since_base_date,
       ROW_NUMBER() OVER(ORDER BY loan_date) AS rn
FROM Loans;


              loan_date                 days_since_base_date   rn
              2008-01-01 00:00:00.000   39446                  1
              2008-01-02 00:00:00.000   39447                  2
              2008-01-03 00:00:00.000   39448                  3
              2008-01-12 00:00:00.000   39457                  4
              2008-01-13 00:00:00.000   39458                  5
              2008-01-29 00:00:00.000   39474                  6
              2008-01-30 00:00:00.000   39475                  7
              2008-01-31 00:00:00.000   39476                  8
-- Solution with ROW_NUMBER
SELECT MIN(loan_date) AS start_date,
       MAX(loan_date) AS end_date
FROM (SELECT loan_date,
             DATEDIFF(DAY, '19000101', loan_date) -
             ROW_NUMBER() OVER(ORDER BY loan_date) AS base
      FROM Loans) AS L
GROUP BY base;
Refactoring SQL for Performance
Refactoring SQL for Performance

Weitere ähnliche Inhalte

Ähnlich wie Refactoring SQL for Performance

Single Message Transforms (SMT) in Kafka Connect | Betül Çetinkaya and Okan Y...
Single Message Transforms (SMT) in Kafka Connect | Betül Çetinkaya and Okan Y...Single Message Transforms (SMT) in Kafka Connect | Betül Çetinkaya and Okan Y...
Single Message Transforms (SMT) in Kafka Connect | Betül Çetinkaya and Okan Y...HostedbyConfluent
 
Project 01 - Data Exploration and Reporting
Project 01 - Data Exploration and ReportingProject 01 - Data Exploration and Reporting
Project 01 - Data Exploration and ReportingAmarnathVenkataraman
 
GPUG Academy: Microsoft Excel and Microsoft Dynamics Receivables Management
GPUG Academy:  Microsoft Excel and Microsoft Dynamics Receivables ManagementGPUG Academy:  Microsoft Excel and Microsoft Dynamics Receivables Management
GPUG Academy: Microsoft Excel and Microsoft Dynamics Receivables ManagementBelinda Allen
 
Final Project.ipynb_checkpointsSpr2019_Decision_Trees_Project1.docx
Final Project.ipynb_checkpointsSpr2019_Decision_Trees_Project1.docxFinal Project.ipynb_checkpointsSpr2019_Decision_Trees_Project1.docx
Final Project.ipynb_checkpointsSpr2019_Decision_Trees_Project1.docxlmelaine
 
[DSC Europe 23][Cryptica] Jovan_Milovanovic-Bank_Statement_Data_Analysis.pdf
[DSC Europe 23][Cryptica] Jovan_Milovanovic-Bank_Statement_Data_Analysis.pdf[DSC Europe 23][Cryptica] Jovan_Milovanovic-Bank_Statement_Data_Analysis.pdf
[DSC Europe 23][Cryptica] Jovan_Milovanovic-Bank_Statement_Data_Analysis.pdfDataScienceConferenc1
 
GPUG Academy - Microsoft Excel & Microsoft Dynamics GP Payables Management (M...
GPUG Academy - Microsoft Excel & Microsoft Dynamics GP Payables Management (M...GPUG Academy - Microsoft Excel & Microsoft Dynamics GP Payables Management (M...
GPUG Academy - Microsoft Excel & Microsoft Dynamics GP Payables Management (M...Belinda Allen
 
Subscribed 2017: Building a Data Pipeline to Engage and Retain Your Subscribers
Subscribed 2017: Building a Data Pipeline to Engage and Retain Your SubscribersSubscribed 2017: Building a Data Pipeline to Engage and Retain Your Subscribers
Subscribed 2017: Building a Data Pipeline to Engage and Retain Your SubscribersZuora, Inc.
 

Ähnlich wie Refactoring SQL for Performance (7)

Single Message Transforms (SMT) in Kafka Connect | Betül Çetinkaya and Okan Y...
Single Message Transforms (SMT) in Kafka Connect | Betül Çetinkaya and Okan Y...Single Message Transforms (SMT) in Kafka Connect | Betül Çetinkaya and Okan Y...
Single Message Transforms (SMT) in Kafka Connect | Betül Çetinkaya and Okan Y...
 
Project 01 - Data Exploration and Reporting
Project 01 - Data Exploration and ReportingProject 01 - Data Exploration and Reporting
Project 01 - Data Exploration and Reporting
 
GPUG Academy: Microsoft Excel and Microsoft Dynamics Receivables Management
GPUG Academy:  Microsoft Excel and Microsoft Dynamics Receivables ManagementGPUG Academy:  Microsoft Excel and Microsoft Dynamics Receivables Management
GPUG Academy: Microsoft Excel and Microsoft Dynamics Receivables Management
 
Final Project.ipynb_checkpointsSpr2019_Decision_Trees_Project1.docx
Final Project.ipynb_checkpointsSpr2019_Decision_Trees_Project1.docxFinal Project.ipynb_checkpointsSpr2019_Decision_Trees_Project1.docx
Final Project.ipynb_checkpointsSpr2019_Decision_Trees_Project1.docx
 
[DSC Europe 23][Cryptica] Jovan_Milovanovic-Bank_Statement_Data_Analysis.pdf
[DSC Europe 23][Cryptica] Jovan_Milovanovic-Bank_Statement_Data_Analysis.pdf[DSC Europe 23][Cryptica] Jovan_Milovanovic-Bank_Statement_Data_Analysis.pdf
[DSC Europe 23][Cryptica] Jovan_Milovanovic-Bank_Statement_Data_Analysis.pdf
 
GPUG Academy - Microsoft Excel & Microsoft Dynamics GP Payables Management (M...
GPUG Academy - Microsoft Excel & Microsoft Dynamics GP Payables Management (M...GPUG Academy - Microsoft Excel & Microsoft Dynamics GP Payables Management (M...
GPUG Academy - Microsoft Excel & Microsoft Dynamics GP Payables Management (M...
 
Subscribed 2017: Building a Data Pipeline to Engage and Retain Your Subscribers
Subscribed 2017: Building a Data Pipeline to Engage and Retain Your SubscribersSubscribed 2017: Building a Data Pipeline to Engage and Retain Your Subscribers
Subscribed 2017: Building a Data Pipeline to Engage and Retain Your Subscribers
 

Kürzlich hochgeladen

Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGSujit Pal
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024BookNet Canada
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Igalia
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 3652toLead Limited
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Paola De la Torre
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesSinan KOZAK
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024Results
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...HostedbyConfluent
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking MenDelhi Call girls
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Allon Mureinik
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdfhans926745
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...gurkirankumar98700
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)Gabriella Davis
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 

Kürzlich hochgeladen (20)

Google AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAGGoogle AI Hackathon: LLM based Evaluator for RAG
Google AI Hackathon: LLM based Evaluator for RAG
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
Transcript: #StandardsGoals for 2024: What’s new for BISAC - Tech Forum 2024
 
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
Raspberry Pi 5: Challenges and Solutions in Bringing up an OpenGL/Vulkan Driv...
 
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
Tech-Forward - Achieving Business Readiness For Copilot in Microsoft 365
 
Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101Salesforce Community Group Quito, Salesforce 101
Salesforce Community Group Quito, Salesforce 101
 
Unblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen FramesUnblocking The Main Thread Solving ANRs and Frozen Frames
Unblocking The Main Thread Solving ANRs and Frozen Frames
 
A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024A Call to Action for Generative AI in 2024
A Call to Action for Generative AI in 2024
 
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
Transforming Data Streams with Kafka Connect: An Introduction to Single Messa...
 
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
Neo4j - How KGs are shaping the future of Generative AI at AWS Summit London ...
 
08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men08448380779 Call Girls In Friends Colony Women Seeking Men
08448380779 Call Girls In Friends Colony Women Seeking Men
 
Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)Injustice - Developers Among Us (SciFiDevCon 2024)
Injustice - Developers Among Us (SciFiDevCon 2024)
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf[2024]Digital Global Overview Report 2024 Meltwater.pdf
[2024]Digital Global Overview Report 2024 Meltwater.pdf
 
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
Kalyanpur ) Call Girls in Lucknow Finest Escorts Service 🍸 8923113531 🎰 Avail...
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)A Domino Admins Adventures (Engage 2024)
A Domino Admins Adventures (Engage 2024)
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 

Refactoring SQL for Performance

  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6. loan_nbr customer_nbr code value 1 1 amount 1500.00 1 1 date 20080110 1 1 type personal 2 2 amount 3500.00 2 2 date 20080215 2 2 type personal CREATE TABLE EAV_Loans ( loan_nbr INT NOT NULL, customer_nbr INT NOT NULL, code VARCHAR(30) NOT NULL, value VARCHAR(200), CONSTRAINT pk_eav_loans PRIMARY KEY (loan_nbr, customer_nbr, code));
  • 7. -- Customers with personal loans over 1000.00 for the period -- Jan 1, 2008 through Jan 31, 2008 SELECT A.loan_nbr, A.customer_nbr, CAST(A.value AS DATETIME) AS loan_date, CAST(B.value AS DECIMAL(15, 2)) AS loan_amount FROM EAV_Loans AS A INNER JOIN EAV_Loans AS B ON A.loan_nbr = B.loan_nbr AND A.customer_nbr = B.customer_nbr INNER JOIN EAV_Loans AS C ON A.loan_nbr = C.loan_nbr AND A.customer_nbr = C.customer_nbr WHERE A.code = 'date' AND CAST(A.value AS DATETIME) >= '20080101' AND CAST(A.value AS DATETIME) < '20080201' AND B.code = 'amount' AND CAST(B.value AS DECIMAL(15, 2)) > 1000.00 AND C.code = 'type' AND C.value = 'personal';
  • 8.
  • 9. SELECT A.loan_nbr, A.customer_nbr, loan_date, loan_amount FROM (SELECT loan_nbr, customer_nbr, CAST(value AS DATETIME) AS loan_date FROM EAV_Loans WHERE code = 'date') AS A INNER JOIN (SELECT loan_nbr, customer_nbr, CAST(value AS DECIMAL(15, 2)) AS loan_amount FROM EAV_Loans WHERE code = 'amount') AS B ON A.loan_nbr = B.loan_nbr AND A.customer_nbr = B.customer_nbr INNER JOIN (SELECT loan_nbr, customer_nbr, value AS loan_type FROM EAV_Loans WHERE code = 'type') AS C ON A.loan_nbr = C.loan_nbr AND A.customer_nbr = C.customer_nbr WHERE loan_date >= '20080101' AND loan_date < '20080201' AND loan_amount > 1000.00 AND loan_type = 'personal';
  • 10. SELECT loan_nbr, customer_nbr, loan_date, loan_amount FROM (SELECT loan_nbr, customer_nbr, MAX(CASE WHEN code = 'date' THEN CAST(value AS DATETIME) END), MAX(CASE WHEN code = 'amount' THEN CAST(value AS DECIMAL(15, 2)) END), MAX(CASE WHEN code = 'type' THEN value END) FROM EAV_Loans GROUP BY loan_nbr, customer_nbr ) AS L(loan_nbr, customer_nbr, loan_date, loan_amount, loan_type) WHERE loan_date >= '20080101' AND loan_date < '20080201' AND loan_amount > 1000.00 AND loan_type = 'personal';
  • 11. loan_nbr customer_nbr loan_date loan_amount loan_type 1 1 2008-01-10 00:00:00.000 1500.00 personal 2 2 2008-02-15 00:00:00.000 3500.00 personal CREATE TABLE Loans ( loan_nbr INT NOT NULL, customer_nbr INT NOT NULL, loan_date DATETIME NOT NULL, loan_amount DECIMAL(15, 2) NOT NULL, loan_type VARCHAR(10) NOT NULL, CONSTRAINT ck_loan_type CHECK (loan_type IN ('personal', 'business')), CONSTRAINT pk_loans PRIMARY KEY (loan_nbr));
  • 12. -- Convert EAV table to normalized INSERT INTO Loans (loan_nbr, customer_nbr, loan_date, loan_amount, loan_type) SELECT loan_nbr, customer_nbr, MAX(CASE WHEN code = 'date' THEN CAST(value AS DATETIME) END), MAX(CASE WHEN code = 'amount' THEN CAST(value AS DECIMAL(15, 2)) END), MAX(CASE WHEN code = 'type' THEN value END) FROM EAV_Loans GROUP BY loan_nbr, customer_nbr;
  • 13. -- Customers with personal loans over 1000.00 -- for period Jan 1, 2008 through Jan 31, 2008 SELECT loan_nbr, customer_nbr, loan_date, loan_amount FROM Loans WHERE loan_date >= '20080101' AND loan_date < '20080201' AND loan_amount > 1000.00 AND loan_type = 'personal';
  • 14. -- Replacement view for legacy code CREATE VIEW EAV_Loans (loan_nbr, customer_nbr, code, value) AS SELECT loan_nbr, customer_nbr, CAST('date' AS VARCHAR(30)), CONVERT(VARCHAR(200), loan_date, 112) FROM Loans UNION SELECT loan_nbr, customer_nbr, CAST('amount' AS VARCHAR(30)), CAST(loan_amount AS VARCHAR(200)) FROM Loans UNION SELECT loan_nbr, customer_nbr, CAST('type' AS VARCHAR(30)), CAST(loan_type AS VARCHAR(200)) FROM Loans;
  • 15.
  • 16.
  • 17. loan_nbr loan_date loan_amount loan_type rk 3 2008-03-11 00:00:00.000 5000.00 business 1 6 2008-03-27 00:00:00.000 4000.00 business 2 7 2008-04-10 00:00:00.000 3500.00 business 3 4 2008-03-12 00:00:00.000 2000.00 personal 1 8 2008-04-12 00:00:00.000 2000.00 personal 2 1 2008-01-01 00:00:00.000 1500.00 personal 3 5 2008-03-25 00:00:00.000 1200.00 personal 4 2 2008-02-15 00:00:00.000 1000.00 personal 5
  • 18. SELECT loan_nbr, loan_date, loan_amount, loan_type, (SELECT COUNT(*) FROM Loans AS L2 WHERE L2.loan_type = L1.loan_type AND (L2.loan_amount > L1.loan_amount OR L2.loan_amount = L1.loan_amount AND L2.loan_nbr <= L1.loan_nbr)) AS rk FROM Loans AS L1 ORDER BY loan_type, rk;
  • 19. SELECT loan_nbr, loan_date, loan_amount, loan_type, ROW_NUMBER() OVER(PARTITION BY loan_type ORDER BY loan_amount DESC, loan_nbr) AS rk FROM Loans ORDER BY loan_type, rk;
  • 20.
  • 21. loan_nbr customer_nbr loan_date loan_amount loan_type 2 2 2008-02-15 00:00:00.000 1000.00 personal 3 1 2008-03-11 00:00:00.000 4500.00 business 4 3 2008-03-12 00:00:00.000 2000.00 personal loan_nbr customer_nbr loan_date loan_amount loan_type 1 1 2008-01-01 00:00:00.000 1500.00 personal 2 2 2008-02-15 00:00:00.000 1000.00 personal 3 1 2008-03-11 00:00:00.000 5000.00 business loan_nbr customer_nbr loan_date loan_amount loan_type 2 2 2008-02-15 00:00:00.000 1000.00 personal 3 1 2008-03-11 00:00:00.000 4500.00 business 4 3 2008-03-12 00:00:00.000 2000.00 personal
  • 22. -- Update changed UPDATE Loans SET loan_amount = (SELECT D.loan_amount FROM DailyChangedLoans AS D WHERE D.loan_nbr = Loans.loan_nbr AND D.loan_amount <> Loans.loan_amount) WHERE EXISTS(SELECT * FROM DailyChangedLoans AS D WHERE D.loan_nbr = Loans.loan_nbr AND D.loan_amount <> Loans.loan_amount); -- Insert new loans INSERT INTO Loans (loan_nbr, customer_nbr, loan_date, loan_amount, loan_type) SELECT loan_nbr, customer_nbr, loan_date, loan_amount, loan_type FROM DailyChangedLoans AS D WHERE NOT EXISTS(SELECT * FROM Loans AS L WHERE D.loan_nbr = L.loan_nbr); -- Remove deleted DELETE FROM Loans WHERE NOT EXISTS(SELECT * FROM DailyChangedLoans AS D WHERE D.loan_nbr = Loans.loan_nbr);
  • 23. -- Using a single MERGE statement MERGE INTO Loans AS L USING DailyChangedLoans AS D ON D.loan_nbr = L.loan_nbr WHEN MATCHED AND L.loan_amount <> D.loan_amount THEN UPDATE SET loan_amount = D.loan_amount WHEN NOT MATCHED THEN INSERT VALUES(D.loan_nbr, D.customer_nbr, D.loan_date, D.loan_amount, D.loan_type) WHEN NOT MATCHED BY SOURCE THEN DELETE;
  • 24.
  • 25.
  • 26. loan_nbr customer_nbr loan_date loan_amount loan_type 1 1 2008-01-01 00:00:00.000 1500.00 personal 2 2 2008-01-02 00:00:00.000 1000.00 personal 3 1 2008-01-03 00:00:00.000 5000.00 business 4 3 2008-01-12 00:00:00.000 2000.00 personal 5 4 2008-01-13 00:00:00.000 1200.00 personal 6 3 2008-01-29 00:00:00.000 4000.00 business 7 5 2008-01-30 00:00:00.000 3500.00 business 8 2 2008-01-31 00:00:00.000 2000.00 personal start_date end_date 2008-01-01 00:00:00.000 2008-01-03 00:00:00.000 2008-01-12 00:00:00.000 2008-01-13 00:00:00.000 2008-01-29 00:00:00.000 2008-01-31 00:00:00.000
  • 27. -- Find last date for date range -- and use as grouping factor SELECT MIN(loan_date) AS start_date, MAX(loan_date) AS end_date FROM (SELECT loan_date, (SELECT MIN(L2.loan_date) FROM Loans AS L2 WHERE L2.loan_date >= L1.loan_date AND NOT EXISTS (SELECT * FROM Loans AS L3 WHERE L3.loan_date = DATEADD(DAY, 1, L2.loan_date)) ) AS base FROM Loans AS L1) AS L GROUP BY base;
  • 28. -- Preparation for solution SELECT loan_date, DATEDIFF(DAY, '19000101', loan_date) AS days_since_base_date, ROW_NUMBER() OVER(ORDER BY loan_date) AS rn FROM Loans; loan_date days_since_base_date rn 2008-01-01 00:00:00.000 39446 1 2008-01-02 00:00:00.000 39447 2 2008-01-03 00:00:00.000 39448 3 2008-01-12 00:00:00.000 39457 4 2008-01-13 00:00:00.000 39458 5 2008-01-29 00:00:00.000 39474 6 2008-01-30 00:00:00.000 39475 7 2008-01-31 00:00:00.000 39476 8
  • 29. -- Solution with ROW_NUMBER SELECT MIN(loan_date) AS start_date, MAX(loan_date) AS end_date FROM (SELECT loan_date, DATEDIFF(DAY, '19000101', loan_date) - ROW_NUMBER() OVER(ORDER BY loan_date) AS base FROM Loans) AS L GROUP BY base;