|  | 
|  | 1 | +--- | 
|  | 2 | +id: sql-advanced-analytics | 
|  | 3 | +title: Advanced Analytical & BI Features in SQL | 
|  | 4 | +sidebar_label: Advanced Analytics | 
|  | 5 | +sidebar_position: 13 | 
|  | 6 | +tags: [sql, analytics, business-intelligence, database, relational-databases] | 
|  | 7 | +description: In this super beginner-friendly guide, you’ll learn about advanced SQL analytical and BI features—powerful tools for summarizing, transforming, and analyzing data like a pro! | 
|  | 8 | +keywords: [sql, analytics, GROUPING SETS, CUBE, ROLLUP, pivot, unpivot, percentiles, ranking, moving averages, sql tutorial, sql for beginners, sql in 2025] | 
|  | 9 | +--- | 
|  | 10 | + | 
|  | 11 | + | 
|  | 12 | + | 
|  | 13 | +## 📙 Welcome to Advanced Analytical & BI Features! | 
|  | 14 | + | 
|  | 15 | +Hey there, SQL beginner! Ready to level up? Advanced analytical and Business Intelligence (BI) features in SQL let you summarize, transform, and analyze data in powerful ways, like generating reports or finding trends. Think of these as your data superhero tools for slicing and dicing information. We’ll use a simple `students` table (with columns like `id`, `name`, `age`, `marks`, and `city`) to explain everything with clear examples. Let’s dive in step by step! | 
|  | 16 | + | 
|  | 17 | +### 📘 What Are Advanced Analytical & BI Features? | 
|  | 18 | + | 
|  | 19 | +These are specialized SQL features for complex data analysis and reporting: | 
|  | 20 | +- **GROUPING SETS, CUBE, ROLLUP**: Advanced grouping for summarizing data at multiple levels. | 
|  | 21 | +- **Pivot & Unpivot Queries**: Transform rows to columns (and vice versa) for better reporting. | 
|  | 22 | +- **Percentile, Ranking, Moving Averages**: Analytical functions for ranking data, finding percentiles, or calculating trends. | 
|  | 23 | + | 
|  | 24 | +> **Pro Tip**: These features are perfect for BI tools and reports, but test them on small datasets first to understand their output! | 
|  | 25 | +
 | 
|  | 26 | +### 📘 GROUPING SETS, CUBE, ROLLUP (Advanced Grouping!) | 
|  | 27 | + | 
|  | 28 | +These features extend GROUP BY to create multiple summary levels in a single query, ideal for reports with subtotals and grand totals. | 
|  | 29 | + | 
|  | 30 | +**Key Concepts**: | 
|  | 31 | +- **GROUPING SETS**: Lets you specify multiple group-by combinations explicitly. | 
|  | 32 | +- **ROLLUP**: Creates hierarchical subtotals (e.g., by city, then overall). | 
|  | 33 | +- **CUBE**: Creates all possible group-by combinations for the specified columns. | 
|  | 34 | + | 
|  | 35 | +**Examples**: | 
|  | 36 | +    :::info | 
|  | 37 | +<Tabs> | 
|  | 38 | +  <TabItem value="GROUPING SETS" label="GROUPING SETS"> | 
|  | 39 | +```sql title="Using GROUPING SETS" | 
|  | 40 | +SELECT city, AVG(marks) AS avg_marks | 
|  | 41 | +FROM students | 
|  | 42 | +GROUP BY GROUPING SETS (city, ()); -- Groups by city and grand total | 
|  | 43 | +``` | 
|  | 44 | +  </TabItem> | 
|  | 45 | + | 
|  | 46 | +  <TabItem value="GROUPING SETS Output" label="Output"> | 
|  | 47 | +| city   | avg_marks | | 
|  | 48 | +|--------|-----------| | 
|  | 49 | +| Mumbai | 88.5      | | 
|  | 50 | +| Delhi  | 75.0      | | 
|  | 51 | +| NULL   | 84.0      | -- Grand total | 
|  | 52 | +  </TabItem> | 
|  | 53 | + | 
|  | 54 | +  <TabItem value="ROLLUP" label="ROLLUP"> | 
|  | 55 | +```sql title="Using ROLLUP" | 
|  | 56 | +SELECT city, age, AVG(marks) AS avg_marks | 
|  | 57 | +FROM students | 
|  | 58 | +GROUP BY ROLLUP (city, age); -- Subtotals for city, then city+age, then grand total | 
|  | 59 | +``` | 
|  | 60 | +  </TabItem> | 
|  | 61 | + | 
|  | 62 | +  <TabItem value="ROLLUP Output" label="Output"> | 
|  | 63 | +| city   | age  | avg_marks | | 
|  | 64 | +|--------|------|-----------| | 
|  | 65 | +| Mumbai | 20   | 85.0      | | 
|  | 66 | +| Mumbai | 22   | 92.0      | | 
|  | 67 | +| Mumbai | NULL | 88.5      | -- Subtotal for Mumbai | 
|  | 68 | +| Delhi  | 19   | 75.0      | | 
|  | 69 | +| Delhi  | NULL | 75.0      | -- Subtotal for Delhi | 
|  | 70 | +| NULL   | NULL | 84.0      | -- Grand total | 
|  | 71 | +  </TabItem> | 
|  | 72 | + | 
|  | 73 | +  <TabItem value="CUBE" label="CUBE"> | 
|  | 74 | +```sql title="Using CUBE" | 
|  | 75 | +SELECT city, age, AVG(marks) AS avg_marks | 
|  | 76 | +FROM students | 
|  | 77 | +GROUP BY CUBE (city, age); -- All combinations: city, age, city+age, grand total | 
|  | 78 | +``` | 
|  | 79 | +  </TabItem> | 
|  | 80 | + | 
|  | 81 | +  <TabItem value="CUBE Output" label="Output"> | 
|  | 82 | +| city   | age  | avg_marks | | 
|  | 83 | +|--------|------|-----------| | 
|  | 84 | +| Mumbai | 20   | 85.0      | | 
|  | 85 | +| Mumbai | 22   | 92.0      | | 
|  | 86 | +| Delhi  | 19   | 75.0      | | 
|  | 87 | +| Mumbai | NULL | 88.5      | -- Subtotal by city | 
|  | 88 | +| Delhi  | NULL | 75.0      | | 
|  | 89 | +| NULL   | 20   | 85.0      | -- Subtotal by age | 
|  | 90 | +| NULL   | 22   | 92.0      | | 
|  | 91 | +| NULL   | 19   | 75.0      | | 
|  | 92 | +| NULL   | NULL | 84.0      | -- Grand total | 
|  | 93 | +  </TabItem> | 
|  | 94 | +</Tabs> | 
|  | 95 | +::: | 
|  | 96 | + | 
|  | 97 | +> **What NOT to Do**:  | 
|  | 98 | +> - Don’t use CUBE with too many columns—it generates many combinations and can slow queries! | 
|  | 99 | +> - Don’t confuse ROLLUP (hierarchical) with CUBE (all combinations); choose based on your reporting needs. | 
|  | 100 | +
 | 
|  | 101 | +### 🔄 Pivot & Unpivot Queries (Transforming Data Layout!) | 
|  | 102 | + | 
|  | 103 | +**PIVOT** transforms rows into columns (e.g., turning cities into column headers), and **UNPIVOT** does the reverse, turning columns into rows. These are great for creating readable reports or normalizing data. | 
|  | 104 | + | 
|  | 105 | +**Key Concepts**: | 
|  | 106 | +- **PIVOT**: Aggregates data and pivots a column’s values into new columns. | 
|  | 107 | +- **UNPIVOT**: Converts columns back into rows, useful for reversing pivoted data. | 
|  | 108 | + | 
|  | 109 | +**Examples**: | 
|  | 110 | +    :::info | 
|  | 111 | +<Tabs> | 
|  | 112 | +  <TabItem value="PIVOT" label="PIVOT"> | 
|  | 113 | +```sql title="Using PIVOT" | 
|  | 114 | +SELECT * | 
|  | 115 | +FROM ( | 
|  | 116 | +    SELECT city, marks | 
|  | 117 | +    FROM students | 
|  | 118 | +) AS SourceTable | 
|  | 119 | +PIVOT ( | 
|  | 120 | +    AVG(marks) | 
|  | 121 | +    FOR city IN ('Mumbai', 'Delhi') | 
|  | 122 | +) AS PivotTable; | 
|  | 123 | +``` | 
|  | 124 | +  </TabItem> | 
|  | 125 | + | 
|  | 126 | +  <TabItem value="PIVOT Output" label="Output"> | 
|  | 127 | +| Mumbai | Delhi | | 
|  | 128 | +|--------|-------| | 
|  | 129 | +| 88.5   | 75.0  | | 
|  | 130 | +  </TabItem> | 
|  | 131 | + | 
|  | 132 | +  <TabItem value="UNPIVOT" label="UNPIVOT"> | 
|  | 133 | +```sql title="Using UNPIVOT" | 
|  | 134 | +SELECT city, avg_marks | 
|  | 135 | +FROM ( | 
|  | 136 | +    SELECT 'Mumbai' AS Mumbai, 'Delhi' AS Delhi | 
|  | 137 | +    FROM (SELECT 88.5 AS Mumbai, 75.0 AS Delhi) AS PivotTable | 
|  | 138 | +) AS SourceTable | 
|  | 139 | +UNPIVOT ( | 
|  | 140 | +    avg_marks FOR city IN (Mumbai, Delhi) | 
|  | 141 | +) AS UnpivotTable; | 
|  | 142 | +``` | 
|  | 143 | +  </TabItem> | 
|  | 144 | + | 
|  | 145 | +  <TabItem value="UNPIVOT Output" label="Output"> | 
|  | 146 | +| city   | avg_marks | | 
|  | 147 | +|--------|-----------| | 
|  | 148 | +| Mumbai | 88.5      | | 
|  | 149 | +| Delhi  | 75.0      | | 
|  | 150 | +  </TabItem> | 
|  | 151 | +</Tabs> | 
|  | 152 | +::: | 
|  | 153 | + | 
|  | 154 | +> **What NOT to Do**:  | 
|  | 155 | +> - Don’t use PIVOT without an aggregate function (e.g., AVG)—it requires one! | 
|  | 156 | +> - Don’t UNPIVOT columns with mismatched data types—it’ll cause errors. | 
|  | 157 | +
 | 
|  | 158 | +### 📘 Percentile, Ranking, Moving Averages (Analytical Functions!) | 
|  | 159 | + | 
|  | 160 | +These **window functions** analyze data without grouping rows, perfect for ranking students, finding percentiles, or calculating trends like moving averages. | 
|  | 161 | + | 
|  | 162 | +**Key Functions**: | 
|  | 163 | +- **Percentile**: E.g., `PERCENTILE_CONT` or `PERCENTILE_DISC` for finding median or other percentiles. | 
|  | 164 | +- **Ranking**: E.g., `RANK`, `DENSE_RANK`, `ROW_NUMBER` for ordering rows. | 
|  | 165 | +- **Moving Averages**: E.g., `AVG` with a window for trends over rows. | 
|  | 166 | + | 
|  | 167 | +**Examples**: | 
|  | 168 | +    :::info | 
|  | 169 | +<Tabs> | 
|  | 170 | +  <TabItem value="Percentile" label="Percentile"> | 
|  | 171 | +```sql title="Using PERCENTILE_CONT" | 
|  | 172 | +SELECT name, marks, | 
|  | 173 | +       PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY marks) OVER () AS median_marks | 
|  | 174 | +FROM students; | 
|  | 175 | +``` | 
|  | 176 | +  </TabItem> | 
|  | 177 | + | 
|  | 178 | +  <TabItem value="Percentile Output" label="Output"> | 
|  | 179 | +| name  | marks | median_marks | | 
|  | 180 | +|-------|-------|--------------| | 
|  | 181 | +| Alice | 85    | 85.0         | | 
|  | 182 | +| Bob   | 92    | 85.0         | | 
|  | 183 | +| Carol | 75    | 85.0         | | 
|  | 184 | +  </TabItem> | 
|  | 185 | + | 
|  | 186 | +  <TabItem value="Ranking" label="Ranking"> | 
|  | 187 | +```sql title="Using RANK and DENSE_RANK" | 
|  | 188 | +SELECT name, marks, | 
|  | 189 | +       RANK() OVER (ORDER BY marks DESC) AS rank, | 
|  | 190 | +       DENSE_RANK() OVER (ORDER BY marks DESC) AS dense_rank | 
|  | 191 | +FROM students; | 
|  | 192 | +``` | 
|  | 193 | +  </TabItem> | 
|  | 194 | + | 
|  | 195 | +  <TabItem value="Ranking Output" label="Output"> | 
|  | 196 | +| name  | marks | rank | dense_rank | | 
|  | 197 | +|-------|-------|------|------------| | 
|  | 198 | +| Bob   | 92    | 1    | 1          | | 
|  | 199 | +| Alice | 85    | 2    | 2          | | 
|  | 200 | +| Carol | 75    | 3    | 3          | | 
|  | 201 | +  </TabItem> | 
|  | 202 | + | 
|  | 203 | +  <TabItem value="Moving Average" label="Moving Average"> | 
|  | 204 | +```sql title="Using Moving Average" | 
|  | 205 | +SELECT name, marks, | 
|  | 206 | +       AVG(marks) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) AS moving_avg | 
|  | 207 | +FROM students; | 
|  | 208 | +``` | 
|  | 209 | +  </TabItem> | 
|  | 210 | + | 
|  | 211 | +  <TabItem value="Moving Average Output" label="Output"> | 
|  | 212 | +| name  | marks | moving_avg | | 
|  | 213 | +|-------|-------|------------| | 
|  | 214 | +| Alice | 85    | 88.5       | -- Avg of Alice, Bob | 
|  | 215 | +| Bob   | 92    | 84.0       | -- Avg of Alice, Bob, Carol | 
|  | 216 | +| Carol | 75    | 83.5       | -- Avg of Bob, Carol | 
|  | 217 | +  </TabItem> | 
|  | 218 | +</Tabs> | 
|  | 219 | +::: | 
|  | 220 | + | 
|  | 221 | +> **What NOT to Do**:  | 
|  | 222 | +> - Don’t use window functions without understanding the `OVER` clause—it defines the window! | 
|  | 223 | +> - Don’t assume all DBMS support `PERCENTILE_CONT` (e.g., MySQL doesn’t)—check your database’s documentation. | 
|  | 224 | +
 | 
|  | 225 | +## ✅ What You’ve Learned | 
|  | 226 | + | 
|  | 227 | +You’re now a pro at SQL advanced analytical and BI features! You’ve mastered: | 
|  | 228 | +- **GROUPING SETS, CUBE, ROLLUP**: Summarizing data at multiple levels. | 
|  | 229 | +- **Pivot & Unpivot**: Transforming rows to columns and back for reports. | 
|  | 230 | +- **Percentiles, Ranking, Moving Averages**: Analyzing data with window functions. | 
|  | 231 | + | 
|  | 232 | +Practice these with the `students` table to create powerful reports and analyses. Follow the “What NOT to Do” tips to keep your queries efficient and error-free! | 
0 commit comments