├── C1-SQL_for_Data_Science ├── ChinookDatabaseSchema.png ├── DataScientistRolePlay.txt ├── SQL_data_science_quiz_1.sql ├── SQL_data_science_quiz_2.sql ├── SQL_data_science_quiz_3.sql ├── SQL_data_science_quiz_4.sql └── YelpDatabaseSchema.png ├── C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL ├── AB_Testing_Final_Assignment.sql ├── Analyze_Test_Results_for_CV.sql ├── Counting_Users.sql ├── Create_a_Rollup_Table.sql ├── Create_a_Test_Metric.sql ├── Error_Codes.sql ├── Flexible_Data_Formats.sql ├── Identifying_Unreliable_Data_Nulls.sql ├── Product_Analysis.sql ├── Promo_Email.sql ├── README.md ├── Test_Assignments.sql ├── week_1 │ ├── Connecting-to-Mode.pdf │ ├── Counting-Users.pdf │ ├── Error-Codes.pdf │ ├── Flexible-Data-Formats.pdf │ ├── Identifying-Unreliable-Data-_-Nulls.pdf │ └── sol.odt ├── week_2 │ └── quiz.txt ├── week_3 │ ├── Create-a-Rollup-Table.pdf │ ├── Product-Analysis.pdf │ ├── Promo-Email.pdf │ └── quiz_3.txt └── week_4 │ └── quiz.odt ├── C3-Distributed-Computing-with-Spark-SQL-main ├── assignments │ ├── module1-assignment1.md │ ├── module2-assignment2.md │ ├── module3-assignment3.md │ └── module4-assignment4.md └── quizes │ ├── module1-quiz.md │ ├── module2-quiz.md │ ├── module3-quiz.md │ └── module4-quiz.md ├── C4-SQL-for-Data-Science-Capstone-Project └── SportsStats │ ├── ERD.png │ ├── athlete_events.zip │ ├── noc_regions.zip │ ├── presentation.pptx │ ├── week1_data_analysis.html │ ├── week1_data_analysis.ipynb │ ├── week1_data_analysis.pdf │ ├── week2_descriptive_stats.ipynb │ ├── week3_beyond_descriptive_stats.ipynb │ └── week4_presentation.pptx ├── LICENSE └── README.md /C1-SQL_for_Data_Science/ChinookDatabaseSchema.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/urbanclimatefr/Coursera-Learn-SQL-Basics-for-Data-Science/844aaf928966f21e0d6a04a6cb76a2e4dba4c7eb/C1-SQL_for_Data_Science/ChinookDatabaseSchema.png -------------------------------------------------------------------------------- /C1-SQL_for_Data_Science/DataScientistRolePlay.txt: -------------------------------------------------------------------------------- 1 | 2 | By: Trent Parkinson 3 | Date: Jan-18th-2018 4 | 5 | Data Scientist Role Play: Profiling and Analyzing the Yelp Dataset Coursera Worksheet 6 | 7 | This is a 2-part assignment. In the first part, you are asked a series of questions that 8 | will help you profile and understand the data just like a data scientist would. For this 9 | first part of the assignment, you will be assessed both on the correctness of your 10 | findings, as well as the code you used to arrive at your answer. You will be graded on 11 | how easy your code is to read, so remember to use proper formatting and comments where 12 | necessary. 13 | 14 | In the second part of the assignment, you are asked to come up with your own inferences 15 | and analysis of the data for a particular research question you want to answer. You will be 16 | required to prepare the dataset for the analysis you choose to do. As with the first part, 17 | you will be graded, in part, on how easy your code is to read, so use proper formatting 18 | and comments to illustrate and communicate your intent as required. 19 | 20 | For both parts of this assignment, use this "worksheet." It provides all the questions 21 | you are being asked, and your job will be to transfer your answers and SQL coding where 22 | indicated into this worksheet so that your peers can review your work. You should be able 23 | to use any Text Editor (Windows Notepad, Apple TextEdit, Notepad ++, Sublime Text, etc.) 24 | to copy and paste your answers. If you are going to use Word or some other page layout 25 | application, just be careful to make sure your answers and code are lined appropriately. 26 | In this case, you may want to save as a PDF to ensure your formatting remains intact 27 | for you reviewer. 28 | 29 | 30 | 31 | Part 1: Yelp Dataset Profiling and Understanding 32 | 33 | 1. Profile the data by finding the total number of records for each of the tables below: 34 | 35 | SELECT COUNT(*) 36 | FROM table 37 | 38 | i. Attribute table = 10000 39 | ii. Business table = 10000 40 | iii. Category table = 10000 41 | iv. Checkin table = 10000 42 | v. elite_years table = 10000 43 | vi. friend table = 10000 44 | vii. hours table = 10000 45 | viii. photo table = 10000 46 | ix. review table = 10000 47 | x. tip table = 10000 48 | xi. user table = 10000 49 | 50 | 51 | 52 | 2. Find the total number of distinct records for each of the keys listed below: 53 | 54 | SELECT COUNT(DISTINCT(key)) 55 | FROM table 56 | 57 | i. Business = id: 10000 58 | ii. Hours = business_id: 1562 59 | iii. Category = business_id: 2643 60 | iv. Attribute = business_id: 1115 61 | v. Review = id:10000, business_id: 8090, user_id: 9581 62 | vi. Checkin = business_id: 493 63 | vii. Photo = id: 10000, business_id: 6493 64 | viii. Tip = user_id: 537, business_id: 3979 65 | ix. User = id: 10000 66 | x. Friend = user_id: 11 67 | xi. Elite_years = user_id: 2780 68 | 69 | 70 | 71 | 3. Are there any columns with null values in the Users table? Indicate "yes," or "no." 72 | 73 | Answer: "no" 74 | 75 | 76 | SQL code used to arrive at answer: 77 | 78 | SELECT COUNT(*) 79 | FROM user 80 | WHERE id IS NULL OR 81 | name IS NULL OR 82 | review_count IS NULL OR 83 | yelping_since IS NULL OR 84 | useful IS NULL OR 85 | funny IS NULL OR 86 | cool IS NULL OR 87 | fans IS NULL OR 88 | average_stars IS NULL OR 89 | compliment_hot IS NULL OR 90 | compliment_more IS NULL OR 91 | compliment_profile IS NULL OR 92 | compliment_cute IS NULL OR 93 | compliment_list IS NULL OR 94 | compliment_note IS NULL OR 95 | compliment_plain IS NULL OR 96 | compliment_cool IS NULL OR 97 | compliment_funny IS NULL OR 98 | compliment_writer IS NULL OR 99 | compliment_photos IS NULL 100 | 101 | 102 | 103 | 4. Find the minimum, maximum, and average value for the following fields: 104 | 105 | SELECT AVG(column) 106 | FROM table 107 | 108 | i. Table: Review, Column: Stars 109 | 110 | min: 1 max: 5 avg: 3.7082 111 | 112 | 113 | ii. Table: Business, Column: Stars 114 | 115 | min: 1 max: 5 avg: 3.6549 116 | 117 | 118 | iii. Table: Tip, Column: Likes 119 | 120 | min: 0 max: 2 avg: 0.0144 121 | 122 | 123 | iv. Table: Checkin, Column: Count 124 | 125 | min: 1 max: 53 avg: 1.9414 126 | 127 | 128 | v. Table: User, Column: Review_count 129 | 130 | min: 0 max: 2000 avg: 24.2995 131 | 132 | 133 | 134 | 5. List the cities with the most reviews in descending order: 135 | 136 | SQL code used to arrive at answer: 137 | 138 | SELECT city, 139 | SUM(review_count) AS reviews 140 | FROM business 141 | GROUP BY city 142 | ORDER BY reviews DESC 143 | 144 | Copy and Paste the Result Below: 145 | 146 | +-----------------+---------+ 147 | | city | reviews | 148 | +-----------------+---------+ 149 | | Las Vegas | 82854 | 150 | | Phoenix | 34503 | 151 | | Toronto | 24113 | 152 | | Scottsdale | 20614 | 153 | | Charlotte | 12523 | 154 | | Henderson | 10871 | 155 | | Tempe | 10504 | 156 | | Pittsburgh | 9798 | 157 | | Montréal | 9448 | 158 | | Chandler | 8112 | 159 | | Mesa | 6875 | 160 | | Gilbert | 6380 | 161 | | Cleveland | 5593 | 162 | | Madison | 5265 | 163 | | Glendale | 4406 | 164 | | Mississauga | 3814 | 165 | | Edinburgh | 2792 | 166 | | Peoria | 2624 | 167 | | North Las Vegas | 2438 | 168 | | Markham | 2352 | 169 | | Champaign | 2029 | 170 | | Stuttgart | 1849 | 171 | | Surprise | 1520 | 172 | | Lakewood | 1465 | 173 | | Goodyear | 1155 | 174 | +-----------------+---------+ 175 | 176 | 177 | 6. Find the distribution of star ratings to the business in the following cities: 178 | 179 | i. Avon 180 | 181 | SQL code used to arrive at answer: 182 | 183 | SELECT stars, 184 | SUM(review_count) AS count 185 | FROM business 186 | WHERE city == 'Avon' 187 | GROUP BY stars 188 | 189 | 190 | Copy and Paste the Resulting Table Below (2 columns - star rating and count): 191 | 192 | +-------+-------+ 193 | | stars | count | 194 | +-------+-------+ 195 | | 1.5 | 10 | 196 | | 2.5 | 6 | 197 | | 3.5 | 88 | 198 | | 4.0 | 21 | 199 | | 4.5 | 31 | 200 | | 5.0 | 3 | 201 | +-------+-------+ 202 | 203 | 204 | ii. Beachwood 205 | 206 | SQL code used to arrive at answer: 207 | 208 | SELECT stars, 209 | SUM(review_count) AS count 210 | FROM business 211 | WHERE city == 'Beachwood' 212 | GROUP BY stars 213 | 214 | Copy and Paste the Resulting Table Below (2 columns - star rating and count): 215 | 216 | +-------+-------+ 217 | | stars | count | 218 | +-------+-------+ 219 | | 2.0 | 8 | 220 | | 2.5 | 3 | 221 | | 3.0 | 11 | 222 | | 3.5 | 6 | 223 | | 4.0 | 69 | 224 | | 4.5 | 17 | 225 | | 5.0 | 23 | 226 | +-------+-------+ 227 | 228 | 229 | 7. Find the top 3 users based on their total number of reviews: 230 | 231 | SQL code used to arrive at answer: 232 | 233 | SELECT id, 234 | name, 235 | review_count 236 | FROM user 237 | ORDER BY review_count DESC 238 | LIMIT 3 239 | 240 | Copy and Paste the Result Below: 241 | 242 | +------------------------+--------+--------------+ 243 | | id | name | review_count | 244 | +------------------------+--------+--------------+ 245 | | -G7Zkl1wIWBBmD0KRy_sCw | Gerald | 2000 | 246 | | -3s52C4zL_DHRK0ULG6qtg | Sara | 1629 | 247 | | -8lbUNlXVSoXqaRRiHiSNg | Yuri | 1339 | 248 | +------------------------+--------+--------------+ 249 | 250 | 8. Does posing more reviews correlate with more fans? 251 | 252 | Yes, but also the amount of time that they have been yelping. The longer they 253 | have been yelping and the more reviews they give has a higher fan count. 254 | 255 | Please explain your findings and interpretation of the results: 256 | 257 | SELECT id, 258 | name, 259 | review_count, 260 | fans, 261 | yelping_since 262 | FROM user 263 | ORDER BY fans DESC 264 | 265 | +------------------------+-----------+--------------+------+---------------------+ 266 | | id | name | review_count | fans | yelping_since | 267 | +------------------------+-----------+--------------+------+---------------------+ 268 | | -9I98YbNQnLdAmcYfb324Q | Amy | 609 | 503 | 2007-07-19 00:00:00 | 269 | | -8EnCioUmDygAbsYZmTeRQ | Mimi | 968 | 497 | 2011-03-30 00:00:00 | 270 | | --2vR0DIsmQ6WfcSzKWigw | Harald | 1153 | 311 | 2012-11-27 00:00:00 | 271 | | -G7Zkl1wIWBBmD0KRy_sCw | Gerald | 2000 | 253 | 2012-12-16 00:00:00 | 272 | | -0IiMAZI2SsQ7VmyzJjokQ | Christine | 930 | 173 | 2009-07-08 00:00:00 | 273 | | -g3XIcCb2b-BD0QBCcq2Sw | Lisa | 813 | 159 | 2009-10-05 00:00:00 | 274 | | -9bbDysuiWeo2VShFJJtcw | Cat | 377 | 133 | 2009-02-05 00:00:00 | 275 | | -FZBTkAZEXoP7CYvRV2ZwQ | William | 1215 | 126 | 2015-02-19 00:00:00 | 276 | | -9da1xk7zgnnfO1uTVYGkA | Fran | 862 | 124 | 2012-04-05 00:00:00 | 277 | | -lh59ko3dxChBSZ9U7LfUw | Lissa | 834 | 120 | 2007-08-14 00:00:00 | 278 | | -B-QEUESGWHPE_889WJaeg | Mark | 861 | 115 | 2009-05-31 00:00:00 | 279 | | -DmqnhW4Omr3YhmnigaqHg | Tiffany | 408 | 111 | 2008-10-28 00:00:00 | 280 | | -cv9PPT7IHux7XUc9dOpkg | bernice | 255 | 105 | 2007-08-29 00:00:00 | 281 | | -DFCC64NXgqrxlO8aLU5rg | Roanna | 1039 | 104 | 2006-03-28 00:00:00 | 282 | | -IgKkE8JvYNWeGu8ze4P8Q | Angela | 694 | 101 | 2010-10-01 00:00:00 | 283 | | -K2Tcgh2EKX6e6HqqIrBIQ | .Hon | 1246 | 101 | 2006-07-19 00:00:00 | 284 | | -4viTt9UC44lWCFJwleMNQ | Ben | 307 | 96 | 2007-03-10 00:00:00 | 285 | | -3i9bhfvrM3F1wsC9XIB8g | Linda | 584 | 89 | 2005-08-07 00:00:00 | 286 | | -kLVfaJytOJY2-QdQoCcNQ | Christina | 842 | 85 | 2012-10-08 00:00:00 | 287 | | -ePh4Prox7ZXnEBNGKyUEA | Jessica | 220 | 84 | 2009-01-12 00:00:00 | 288 | | -4BEUkLvHQntN6qPfKJP2w | Greg | 408 | 81 | 2008-02-16 00:00:00 | 289 | | -C-l8EHSLXtZZVfUAUhsPA | Nieves | 178 | 80 | 2013-07-08 00:00:00 | 290 | | -dw8f7FLaUmWR7bfJ_Yf0w | Sui | 754 | 78 | 2009-09-07 00:00:00 | 291 | | -8lbUNlXVSoXqaRRiHiSNg | Yuri | 1339 | 76 | 2008-01-03 00:00:00 | 292 | | -0zEEaDFIjABtPQni0XlHA | Nicole | 161 | 73 | 2009-04-30 00:00:00 | 293 | +------------------------+-----------+--------------+------+---------------------+ 294 | 295 | 296 | 297 | 9. Are there more reviews with the word "love" or with the word "hate" in them? 298 | 299 | Answer: love has 1780, while hate only has 232 :) 'love prevails' 300 | 301 | 302 | SQL code used to arrive at answer: 303 | 304 | SELECT COUNT(*) SELECT COUNT(*) 305 | FROM review FROM review 306 | WHERE text LIKE "%love%" WHERE text LIKE "%hate%" 307 | 308 | = 1780 = 232 309 | 310 | 10. Find the top 10 users with the most fans: 311 | 312 | SQL code used to arrive at answer: 313 | 314 | SELECT id, 315 | name, 316 | fans 317 | FROM user 318 | ORDER BY fans DESC 319 | LIMIT 10 320 | 321 | 322 | Copy and Paste the Result Below: 323 | 324 | +------------------------+-----------+------+ 325 | | id | name | fans | 326 | +------------------------+-----------+------+ 327 | | -9I98YbNQnLdAmcYfb324Q | Amy | 503 | 328 | | -8EnCioUmDygAbsYZmTeRQ | Mimi | 497 | 329 | | --2vR0DIsmQ6WfcSzKWigw | Harald | 311 | 330 | | -G7Zkl1wIWBBmD0KRy_sCw | Gerald | 253 | 331 | | -0IiMAZI2SsQ7VmyzJjokQ | Christine | 173 | 332 | | -g3XIcCb2b-BD0QBCcq2Sw | Lisa | 159 | 333 | | -9bbDysuiWeo2VShFJJtcw | Cat | 133 | 334 | | -FZBTkAZEXoP7CYvRV2ZwQ | William | 126 | 335 | | -9da1xk7zgnnfO1uTVYGkA | Fran | 124 | 336 | | -lh59ko3dxChBSZ9U7LfUw | Lissa | 120 | 337 | +------------------------+-----------+------+ 338 | 339 | 340 | 11. Is there a strong correlation between having a high number of fans and being listed 341 | as "useful" or "funny?" 342 | 343 | Yes, see interpretation. 344 | 345 | SQL code used to arrive at answer: 346 | 347 | SELECT name, 348 | fans, 349 | useful, 350 | funny, 351 | review_count, 352 | yelping_since 353 | FROM user 354 | ORDER BY fans DESC 355 | 356 | Copy and Paste the Result Below: 357 | 358 | +-----------+------+--------+--------+--------------+---------------------+ 359 | | name | fans | useful | funny | review_count | yelping_since | 360 | +-----------+------+--------+--------+--------------+---------------------+ 361 | | Amy | 503 | 3226 | 2554 | 609 | 2007-07-19 00:00:00 | 362 | | Mimi | 497 | 257 | 138 | 968 | 2011-03-30 00:00:00 | 363 | | Harald | 311 | 122921 | 122419 | 1153 | 2012-11-27 00:00:00 | 364 | | Gerald | 253 | 17524 | 2324 | 2000 | 2012-12-16 00:00:00 | 365 | | Christine | 173 | 4834 | 6646 | 930 | 2009-07-08 00:00:00 | 366 | | Lisa | 159 | 48 | 13 | 813 | 2009-10-05 00:00:00 | 367 | | Cat | 133 | 1062 | 672 | 377 | 2009-02-05 00:00:00 | 368 | | William | 126 | 9363 | 9361 | 1215 | 2015-02-19 00:00:00 | 369 | | Fran | 124 | 9851 | 7606 | 862 | 2012-04-05 00:00:00 | 370 | | Lissa | 120 | 455 | 150 | 834 | 2007-08-14 00:00:00 | 371 | | Mark | 115 | 4008 | 570 | 861 | 2009-05-31 00:00:00 | 372 | | Tiffany | 111 | 1366 | 984 | 408 | 2008-10-28 00:00:00 | 373 | | bernice | 105 | 120 | 112 | 255 | 2007-08-29 00:00:00 | 374 | | Roanna | 104 | 2995 | 1188 | 1039 | 2006-03-28 00:00:00 | 375 | | Angela | 101 | 158 | 164 | 694 | 2010-10-01 00:00:00 | 376 | | .Hon | 101 | 7850 | 5851 | 1246 | 2006-07-19 00:00:00 | 377 | | Ben | 96 | 1180 | 1155 | 307 | 2007-03-10 00:00:00 | 378 | | Linda | 89 | 3177 | 2736 | 584 | 2005-08-07 00:00:00 | 379 | | Christina | 85 | 158 | 34 | 842 | 2012-10-08 00:00:00 | 380 | | Jessica | 84 | 2161 | 2091 | 220 | 2009-01-12 00:00:00 | 381 | | Greg | 81 | 820 | 753 | 408 | 2008-02-16 00:00:00 | 382 | | Nieves | 80 | 1091 | 774 | 178 | 2013-07-08 00:00:00 | 383 | | Sui | 78 | 9 | 18 | 754 | 2009-09-07 00:00:00 | 384 | | Yuri | 76 | 1166 | 220 | 1339 | 2008-01-03 00:00:00 | 385 | | Nicole | 73 | 13 | 10 | 161 | 2009-04-30 00:00:00 | 386 | +-----------+------+--------+--------+--------------+---------------------+ 387 | 388 | 389 | Please explain your findings and interpretation of the results: 390 | 391 | Yes, but there does seem to be one major outlier, number three Harald. The 392 | other users seem to have a correlation with more `useful` and `funny` 393 | results in more fans, but also in conjunction with review_count and time 394 | they have been yelping. 395 | 396 | 397 | 398 | Part 2: Inferences and Analysis 399 | 400 | 1. Pick one city and category of your choice and group the businesses in that city 401 | or category by their overall star rating. Compare the businesses with 2-3 stars to 402 | the businesses with 4-5 stars and answer the following questions. Include your code. 403 | 404 | 405 | i. Do the two groups you chose to analyze have a different distribution of hours? 406 | 407 | The 4-5 star group seems to have shorter hours then the 2-3 star group. 408 | Please note the query returned only three businesses so not a great 409 | sample size. 410 | 411 | ii. Do the two groups you chose to analyze have a different number of reviews? 412 | 413 | Yes and no, one of the 4-5 star group has a lot more reviews but then the other 414 | 4-5 star group has close to the same number of reviews as the 2-3 star group 415 | 416 | iii. Are you able to infer anything from the location data provided between these two 417 | groups? Explain. 418 | 419 | No, every business is in a different zip-code. 420 | 421 | SQL code used for analysis: 422 | 423 | SELECT B.name, 424 | B.review_count, 425 | H.hours, 426 | postal_code, 427 | CASE 428 | WHEN hours LIKE "%monday%" THEN 1 429 | WHEN hours LIKE "%tuesday%" THEN 2 430 | WHEN hours LIKE "%wednesday%" THEN 3 431 | WHEN hours LIKE "%thursday%" THEN 4 432 | WHEN hours LIKE "%friday%" THEN 5 433 | WHEN hours LIKE "%saturday%" THEN 6 434 | WHEN hours LIKE "%sunday%" THEN 7 435 | END AS ord, 436 | CASE 437 | WHEN B.stars BETWEEN 2 AND 3 THEN '2-3 stars' 438 | WHEN B.stars BETWEEN 4 AND 5 THEN '4-5 stars' 439 | END AS star_rating 440 | FROM business B INNER JOIN hours H 441 | ON B.id = H.business_id 442 | INNER JOIN category C 443 | ON C.business_id = B.id 444 | WHERE (B.city == 'Las Vegas' 445 | AND 446 | C.category LIKE 'shopping') 447 | AND 448 | (B.stars BETWEEN 2 AND 3 449 | OR 450 | B.stars BETWEEN 4 AND 5) 451 | GROUP BY stars,ord 452 | ORDER BY ord,star_rating ASC 453 | 454 | 455 | 456 | 2. Group business based on the ones that are open and the ones that are closed. What 457 | differences can you find between the ones that are still open and the ones that are 458 | closed? List at least two differences and the SQL code you used to arrive at your 459 | answer. 460 | 461 | i. Difference 1: 462 | 463 | The businesses that are open tend to have more reviews than ones that 464 | are closed on average. 465 | 466 | Open: AVG(review_count) = 31.757 467 | Closed: AVG(review_count0 = 23.198 468 | 469 | 470 | ii. Difference 2: 471 | 472 | The average star rating is higher for businesses that are open than 473 | businesses that are closed. 474 | 475 | Open: AVG(stars) = 3.679 476 | Closed: AVG(stars) = 3.520 477 | 478 | 479 | SQL code used for analysis: 480 | 481 | SELECT COUNT(DISTINCT(id)), 482 | AVG(review_count), 483 | SUM(review_count), 484 | AVG(stars), 485 | is_open 486 | FROM business 487 | GROUP BY is_open 488 | 489 | 490 | 491 | 3. For this last part of your analysis, you are going to choose the type of analysis you 492 | want to conduct on the Yelp dataset and are going to prepare the data for analysis. 493 | 494 | Ideas for analysis include: Parsing out keywords and business attributes for sentiment 495 | analysis, clustering businesses to find commonalities or anomalies between them, 496 | predicting the overall star rating for a business, predicting the number of fans a 497 | user will have, and so on. These are just a few examples to get you started, so feel 498 | free to be creative and come up with your own problem you want to solve. Provide 499 | answers, in-line, to all of the following: 500 | 501 | i. Indicate the type of analysis you chose to do: 502 | 503 | Predicting whether a business will stay open or close. We wish not to explicitly 504 | examine the text of the reviews, but this would be an interesting analysis. 505 | 506 | ii. Write 1-2 brief paragraphs on the type of data you will need for your analysis 507 | and why you chose that data: 508 | 509 | To better help businesses understand the importance of different factors which 510 | will help their business stay open. Some data that may be important; number of 511 | reviews, star rating of business, hours open, and of course location location 512 | location. We will gather the latitude and longitude as well as city, state, 513 | postal_code, and address to make processing easier later on. Categories and 514 | attributes will be used to better distinguish between different types of 515 | businesses. `is_open` will determine which business is open and which business 516 | have closed (not hours) but permanently. 517 | 518 | iii. Output of your finished dataset: 519 | 520 | +------------------------+--------------------------------+-----------------------------+---------------+-------+-------------+----------+-----------+--------------+-------+--------------+---------------+-----------------+----------------+--------------+----------------+--------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------+ 521 | | id | name | address | city | state | postal_code | latitude | longitude | review_count | stars | monday_hours | tuesday_hours | wednesday_hours | thursday_hours | friday_hours | saturday_hours | sunday_hours | categories | attributes | is_open | 522 | +------------------------+--------------------------------+-----------------------------+---------------+-------+-------------+----------+-----------+--------------+-------+--------------+---------------+-----------------+----------------+--------------+----------------+--------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------+ 523 | | -0DET7VdEQOJVJ_v6klEug | Flaming Kitchen | 3235 York Regional Road 7 | Markham | ON | L3R 3P9 | 43.8484 | -79.3487 | 25 | 3.0 | 12:00-23:00 | 12:00-23:00 | 12:00-23:00 | 12:00-23:00 | 12:00-23:00 | 12:00-23:00 | 12:00-23:00 | Asian Fusion,Restaurants | RestaurantsTableService,GoodForMeal,Alcohol,Caters,HasTV,RestaurantsGoodForGroups,NoiseLevel,WiFi,RestaurantsAttire,RestaurantsReservations,OutdoorSeating,RestaurantsPriceRange2,BikeParking,RestaurantsDelivery,Ambience,RestaurantsTakeOut,GoodForKids,BusinessParking | 1 | 524 | | -2HjuT4yjLZ3b5f_abD87Q | Freeman's Car Stereo | 4821 South Blvd | Charlotte | NC | 28217 | 35.1727 | -80.8755 | 8 | 3.5 | 9:00-19:00 | 9:00-19:00 | 9:00-19:00 | 9:00-19:00 | 9:00-19:00 | 9:00-17:00 | None | Electronics,Shopping,Automotive,Car Stereo Installation | BusinessAcceptsCreditCards,RestaurantsPriceRange2,BusinessParking,WheelchairAccessible | 1 | 525 | | -CdstAUdEvci8GeJG8owpQ | Motors & More | 2315 Highland Dr | Las Vegas | NV | 89102 | 36.1465 | -115.167 | 7 | 5.0 | 7:00-17:00 | 7:00-17:00 | 7:00-17:00 | 7:00-17:00 | 7:00-17:00 | 8:00-12:00 | None | Home Services,Solar Installation,Heating & Air Conditioning/HVAC | BusinessAcceptsCreditCards,BusinessAcceptsBitcoin,ByAppointmentOnly | 1 | 526 | | -K4gAv8_vjx8-2BxkVeRkA | Baby Cakes | 4145 Erie St | Willoughby | OH | 44094 | 41.6399 | -81.4064 | 5 | 3.5 | None | 11:00-17:00 | 11:00-17:00 | 11:00-20:00 | 11:00-17:00 | 10:00-17:00 | None | Bakeries,Food | BusinessAcceptsCreditCards,RestaurantsTakeOut,WheelchairAccessible,RestaurantsDelivery | 1 | 527 | | -PtTGvWsckUL8tTutHr6Ew | Snip-its Rocky River | 21609 Center Ridge Rd | Rocky River | OH | 44116 | 41.4595 | -81.8587 | 18 | 2.5 | 10:00-19:00 | 10:00-19:00 | 10:00-19:00 | 10:00-19:00 | 10:00-19:00 | 9:00-17:30 | 10:00-16:00 | Beauty & Spas,Hair Salons | BusinessAcceptsCreditCards,RestaurantsPriceRange2,GoodForKids,BusinessParking,ByAppointmentOnly | 1 | 528 | | -ayZoW_iNDsunYXX_0x1YQ | Standard Restaurant Supply | 2922 E McDowell Rd | Phoenix | AZ | 85008 | 33.4664 | -112.018 | 15 | 3.5 | 8:00-18:00 | 8:00-18:00 | 8:00-18:00 | 8:00-18:00 | 8:00-18:00 | 9:00-17:00 | None | Shopping,Wholesalers,Restaurant Supplies,Professional Services,Wholesale Stores | BusinessAcceptsCreditCards,RestaurantsPriceRange2,BusinessParking,BikeParking,WheelchairAccessible | 1 | 529 | | -d9qyfNhLMQwVVg_raBKeg | What A Bagel | 973 Eglinton Avenue W | York | ON | M6C 2C4 | 43.6999 | -79.4295 | 8 | 3.0 | 6:00-15:30 | 6:00-15:30 | 6:00-15:30 | 6:00-15:30 | 6:00-15:30 | 6:00-15:30 | None | Restaurants,Bagels,Breakfast & Brunch,Food | NoiseLevel,RestaurantsAttire,RestaurantsTableService,OutdoorSeating | 1 | 530 | | -hjbcaxaU9yYXY2iI-49sw | Pinnacle Fencing Solutions | | Phoenix | AZ | 85060 | 33.4805 | -111.997 | 13 | 4.0 | 8:00-16:00 | 8:00-16:00 | 8:00-16:00 | 8:00-16:00 | 8:00-16:00 | None | None | Home Services,Contractors,Fences & Gates | BusinessAcceptsCreditCards,ByAppointmentOnly | 1 | 531 | | -iu4FxdfxN4rU4Fu9BjiFw | Alterations Express | 17240 Royalton Rd | Strongsville | OH | 44136 | 41.3141 | -81.8207 | 3 | 4.0 | 8:00-19:00 | 8:00-19:00 | 8:00-19:00 | 8:00-19:00 | 8:00-19:00 | 8:00-18:00 | None | Shopping,Bridal,Dry Cleaning & Laundry,Local Services,Sewing & Alterations | BusinessParking,BusinessAcceptsCreditCards,RestaurantsPriceRange2,BusinessAcceptsBitcoin,BikeParking,ByAppointmentOnly,WheelchairAccessible | 1 | 532 | | -j4NsiRzSMrMk2N_bGH_SA | Extra Space Storage | 2880 W Elliot Rd | Chandler | AZ | 85224 | 33.3496 | -111.892 | 5 | 4.0 | 8:00-17:30 | 8:00-17:30 | 8:00-17:30 | 8:00-17:30 | 8:00-17:30 | 8:00-17:30 | 10:00-14:00 | Home Services,Self Storage,Movers,Shopping,Local Services,Home Decor,Home & Garden | BusinessAcceptsCreditCards | 1 | 533 | | -uiBBVWI6tMDm2JFbZFrOw | Gussied Up | 1090 Bathurst St | Toronto | ON | M5R 1W5 | 43.6727 | -79.4142 | 6 | 4.5 | None | 11:00-19:00 | 11:00-19:00 | 11:00-19:00 | 11:00-19:00 | 11:00-17:00 | 12:00-16:00 | Women's Clothing,Shopping,Fashion | BusinessAcceptsCreditCards,RestaurantsPriceRange2,BusinessParking,BikeParking | 1 | 534 | | 0-aPEeNc2zVb5Gp-i7Ckqg | Buddy's Muffler & Exhaust | 1509 Hickory Grove Rd | Gastonia | NC | 28056 | 35.2772 | -81.06 | 4 | 5.0 | 8:30-17:00 | 8:30-17:00 | 8:30-17:00 | 8:30-17:00 | 8:30-17:00 | 9:00-15:00 | None | Automotive,Auto Repair | BusinessAcceptsCreditCards | 1 | 535 | | 01xXe2m_z048W5gcBFpoJA | Five Guys | 2641 N 44th St, Ste 100 | Phoenix | AZ | 85008 | 33.478 | -111.986 | 63 | 3.5 | 10:00-22:00 | 10:00-22:00 | 10:00-22:00 | 10:00-22:00 | 10:00-22:00 | 10:00-22:00 | 10:00-22:00 | American (New),Burgers,Fast Food,Restaurants | RestaurantsTableService,GoodForMeal,Alcohol,Caters,HasTV,RestaurantsGoodForGroups,NoiseLevel,WiFi,RestaurantsAttire,RestaurantsReservations,OutdoorSeating,BusinessAcceptsCreditCards,RestaurantsPriceRange2,BikeParking,RestaurantsDelivery,Ambience,RestaurantsTakeOut,GoodForKids,DriveThru,BusinessParking | 1 | 536 | | 06I2r8S3tHP_LwGnnkk6Uw | All Storage - Anthem | 2620 W Horizon Ridge Pkwy | Henderson | NV | 89052 | 36.0021 | -115.102 | 3 | 3.5 | 9:00-16:30 | 9:00-16:30 | 9:00-16:30 | 9:00-16:30 | 9:00-16:30 | 9:00-16:30 | None | Truck Rental,Local Services,Self Storage,Parking,Automotive | BusinessAcceptsCreditCards,BusinessAcceptsBitcoin | 1 | 537 | | 07h3mGtTovPJE660nX6E-A | Mood | 1 Greenside Place | Edinburgh | EDH | EH1 3AA | 55.957 | -3.18502 | 11 | 2.0 | None | None | None | 22:30-3:00 | 22:00-3:00 | 22:00-3:00 | 22:30-3:00 | Dance Clubs,Nightlife | Alcohol,OutdoorSeating,BusinessAcceptsCreditCards,RestaurantsPriceRange2,AgesAllowed,Music,Smoking,RestaurantsGoodForGroups,WheelchairAccessible | 0 | 538 | | 0AJF-USLN6K5T4caooDdjw | Starbucks | 4605 E Chandler Blvd, Ste A | Phoenix | AZ | 85048 | 33.3044 | -111.984 | 52 | 3.0 | 5:00-20:00 | 5:00-20:00 | 5:00-20:00 | 5:00-20:30 | 5:00-20:00 | 5:00-20:00 | 5:00-20:00 | Coffee & Tea,Food | BusinessParking,Caters,WiFi,OutdoorSeating,BusinessAcceptsCreditCards,RestaurantsPriceRange2,BikeParking,RestaurantsTakeOut | 1 | 539 | | 0B3W6KxkD3o4W4l6cq735w | Big Smoke Burger | 260 Yonge Street | Toronto | ON | M4B 2L9 | 43.6546 | -79.3805 | 47 | 3.0 | 10:30-21:00 | 10:30-21:00 | 10:30-21:00 | 10:30-21:00 | 10:30-21:00 | 10:30-21:00 | 11:00-19:00 | Poutineries,Burgers,Restaurants | RestaurantsTableService,GoodForMeal,Alcohol,Caters,HasTV,RestaurantsGoodForGroups,NoiseLevel,WiFi,RestaurantsAttire,RestaurantsReservations,OutdoorSeating,BusinessAcceptsCreditCards,RestaurantsPriceRange2,WheelchairAccessible,BikeParking,RestaurantsDelivery,Ambience,RestaurantsTakeOut,GoodForKids,DriveThru,BusinessParking | 1 | 540 | | 0IySwcfqwJjpHPsYwjpAkg | Subway | 2904 Yorkmont Rd | Charlotte | NC | 28208 | 35.1903 | -80.9288 | 7 | 3.5 | 6:00-22:00 | 6:00-22:00 | 6:00-22:00 | 6:00-22:00 | 6:00-22:00 | 10:00-21:00 | None | Fast Food,Restaurants,Sandwiches | Ambience,RestaurantsPriceRange2,GoodForKids | 1 | 541 | | 0K2rKvqdBmiOAUTebcUohQ | Red Rock Canyon Visitor Center | 1000 Scenic Loop Dr | Las Vegas | NV | 89161 | 36.1357 | -115.428 | 32 | 4.5 | 8:00-16:30 | 8:00-16:30 | 8:00-16:30 | 8:00-16:30 | 8:00-16:30 | 8:00-16:30 | 8:00-16:30 | Education,Visitor Centers,Professional Services,Special Education,Local Services,Community Service/Non-Profit,Hotels & Travel,Travel Services,Gift Shops,Shopping,Parks,Hiking,Flowers & Gifts,Active Life | BusinessAcceptsCreditCards,GoodForKids | 1 | 542 | | 0Ni7Stqt4RFWDGjOYRi2Bw | Scent From Above Company | 2501 W Behrend Dr, Ste 67 | Scottsdale | AZ | 85027 | 33.6656 | -112.111 | 14 | 4.5 | 6:00-16:00 | 6:00-16:00 | 6:00-16:00 | 6:00-16:00 | 6:00-16:00 | None | None | Home Cleaning,Local Services,Professional Services,Carpet Cleaning,Home Services,Office Cleaning,Window Washing | BusinessAcceptsCreditCards,ByAppointmentOnly | 1 | 543 | | 0WBMEfqXQnEOAIkV-uCW6w | The Charlotte Room | 19 Charlotte Street | Toronto | ON | M5V 2H5 | 43.6466 | -79.3938 | 10 | 3.5 | 15:00-1:00 | 15:00-1:00 | 15:00-1:00 | 15:00-1:00 | 15:00-2:00 | 18:00-2:00 | None | Event Planning & Services,Bars,Nightlife,Lounges,Pool Halls,Venues & Event Spaces | BusinessParking,HasTV,CoatCheck,NoiseLevel,OutdoorSeating,BusinessAcceptsCreditCards,RestaurantsPriceRange2,Music,WheelchairAccessible,Smoking,Ambience,BestNights,RestaurantsGoodForGroups,HappyHour,GoodForDancing,Alcohol | 0 | 544 | | 0Y3lHyqRHfWOBuQlS1bM0g | PC Savants | 11966 W Candelaria Ct | Sun City | AZ | 85373 | 33.6901 | -112.319 | 11 | 5.0 | 10:00-19:00 | 10:00-19:00 | 10:00-19:00 | 10:00-19:00 | 10:00-19:00 | 11:00-18:00 | 11:00-18:00 | IT Services & Computer Repair,Electronics Repair,Local Services,Mobile Phone Repair | BusinessAcceptsCreditCards,BusinessAcceptsBitcoin | 1 | 545 | | 0aKsGxx7XP2TMs_fn_9xVw | Sweet Ruby Jane Confections | 8975 S Eastern Ave, Ste 3-B | Las Vegas | NV | 89123 | 36.015 | -115.118 | 30 | 4.0 | 10:00-19:00 | 10:00-19:00 | 10:00-19:00 | 10:00-19:00 | 10:00-19:00 | 10:00-19:00 | None | Food,Chocolatiers & Shops,Bakeries,Specialty Food,Desserts | BusinessAcceptsCreditCards,RestaurantsPriceRange2,BusinessParking,WheelchairAccessible | 0 | 546 | | 0cxO1Lx2Pi7u6ftWX3Wksg | Oinky's Pork Chop Heaven | 22483 Emery Rd | North Randall | OH | 44128 | 41.4352 | -81.5214 | 3 | 3.0 | 6:00-23:00 | 6:00-23:00 | 6:00-23:00 | 6:00-23:00 | 6:00-23:00 | 6:00-23:00 | 6:00-23:00 | Soul Food,Restaurants | RestaurantsAttire,RestaurantsGoodForGroups,GoodForKids,RestaurantsReservations,RestaurantsTakeOut | 1 | 547 | | 0e-j5VcEn54EZT-FKCUZdw | Sushi Osaka | 5084 Dundas Street W | Toronto | ON | M9A 1C2 | 43.6452 | -79.5324 | 8 | 4.5 | 11:00-23:00 | 11:00-23:00 | 11:00-23:00 | 11:00-23:00 | 11:00-23:00 | 11:00-23:00 | 14:00-23:00 | Sushi Bars,Restaurants,Japanese,Korean | RestaurantsTakeOut,WiFi,RestaurantsGoodForGroups,RestaurantsReservations | 1 | 548 | +------------------------+--------------------------------+-----------------------------+---------------+-------+-------------+----------+-----------+--------------+-------+--------------+---------------+-----------------+----------------+--------------+----------------+--------------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+---------+ 549 | 550 | iv. Provide the SQL code you used to create your final dataset: 551 | 552 | SELECT B.id, 553 | B.name, 554 | B.address, 555 | B.city, 556 | B.state, 557 | B.postal_code, 558 | B.latitude, 559 | B.longitude, 560 | B.review_count, 561 | B.stars, 562 | MAX(CASE 563 | WHEN H.hours LIKE "%monday%" THEN TRIM(H.hours,'%MondayTuesWednesThursFriSatSun|%') 564 | END) AS monday_hours, 565 | MAX(CASE 566 | WHEN H.hours LIKE "%tuesday%" THEN TRIM(H.hours,'%MondayTuesWednesThursFriSatSun|%') 567 | END) AS tuesday_hours, 568 | MAX(CASE 569 | WHEN H.hours LIKE "%wednesday%" THEN TRIM(H.hours,'%MondayTuesWednesThursFriSatSun|%') 570 | END) AS wednesday_hours, 571 | MAX(CASE 572 | WHEN H.hours LIKE "%thursday%" THEN TRIM(H.hours,'%MondayTuesWednesThursFriSatSun|%') 573 | END) AS thursday_hours, 574 | MAX(CASE 575 | WHEN H.hours LIKE "%friday%" THEN TRIM(H.hours,'%MondayTuesWednesThursFriSatSun|%') 576 | END) AS friday_hours, 577 | MAX(CASE 578 | WHEN H.hours LIKE "%saturday%" THEN TRIM(H.hours,'%MondayTuesWednesThursFriSatSun|%') 579 | END) AS saturday_hours, 580 | MAX(CASE 581 | WHEN H.hours LIKE "%sunday%" THEN TRIM(H.hours,'%MondayTuesWednesThursFriSatSun|%') 582 | END) AS sunday_hours, 583 | GROUP_CONCAT(DISTINCT(C.category)) AS categories, 584 | GROUP_CONCAT(DISTINCT(A.name)) AS attributes, 585 | B.is_open 586 | FROM business B 587 | INNER JOIN hours H 588 | ON B.id = H.business_id 589 | INNER JOIN category C 590 | ON B.id = C.business_id 591 | INNER JOIN attribute A 592 | ON B.id = A.business_id 593 | GROUP BY B.id -------------------------------------------------------------------------------- /C1-SQL_for_Data_Science/SQL_data_science_quiz_1.sql: -------------------------------------------------------------------------------- 1 | --Q1) Retrieve all the records from the Employees table. 2 | 3 | SELECT * FROM Employees 4 | 5 | ------------------------------------------------------------------------------------ 6 | 7 | --Q2) Retrieve the FirstName, LastName, Birthdate, Address, City, and State from 8 | -- the Employees table. 9 | 10 | SELECT FirstName, LastName, Birthdate, Address, City, State 11 | FROM Employees 12 | WHERE BirthDate = '1965-03-03 00:00:00' 13 | 14 | ------------------------------------------------------------------------------------ 15 | 16 | --Q3) Retrieve all the columns from the Tracks table, but only return 20 rows. 17 | 18 | select * from Tracks 19 | limit 20 -------------------------------------------------------------------------------- /C1-SQL_for_Data_Science/SQL_data_science_quiz_2.sql: -------------------------------------------------------------------------------- 1 | --Q1) Find all the tracks that have a length of 5,000,000 milliseconds or more. 2 | 3 | SELECT COUNT(TrackId) 4 | FROM TRACKS 5 | WHERE Milliseconds >= 5000000 6 | 7 | ------------------------------------------------------------------------------------ 8 | 9 | --Q2) Find all the invoices whose total is between $5 and $15 dollars. 10 | 11 | SELECT InvoiceID,Total 12 | FROM Invoices 13 | WHERE Total > 5 AND Total < 15 14 | 15 | ------------------------------------------------------------------------------------ 16 | 17 | --Q3) Find all the customers from the following States: RJ, DF, AB, BC, CA, WA, NY. 18 | 19 | SELECT FirstName, LastName, Company, State 20 | FROM Customers 21 | WHERE State IN ('RJ','DF','AB','BC','CA','WA','NY') 22 | 23 | ------------------------------------------------------------------------------------ 24 | 25 | --Q4) Find all the invoices for customer 56 and 58 where the total was between 26 | -- $1.00 and $5.00. 27 | 28 | SELECT CustomerId, InvoiceId, Total, InvoiceDate 29 | FROM Invoices 30 | WHERE CustomerID IN (56,58) AND 31 | Total BETWEEN 1 AND 5 32 | 33 | ------------------------------------------------------------------------------------ 34 | 35 | --Q5) Find all the tracks whose name starts with 'All'. 36 | 37 | SELECT TrackId, Name 38 | FROM Tracks 39 | WHERE Name LIKE 'All%' 40 | 41 | ------------------------------------------------------------------------------------ 42 | 43 | --Q6) Find all the customer emails that start with "J" and are from gmail.com. 44 | 45 | SELECT CustomerId, Email 46 | FROM Customers 47 | WHERE Email LIKE "J%@gmail.com" 48 | 49 | ------------------------------------------------------------------------------------ 50 | 51 | --Q7) Find all the invoices from Brasilia, Edmonton, and Vancouver and sort in 52 | -- descending order by invoice ID. 53 | 54 | SELECT InvoiceId, BillingCity, Total 55 | FROM Invoices 56 | WHERE BillingCity IN ('Brasilia','Edmonton','Vancouver') 57 | ORDER BY InvoiceId DESC 58 | 59 | ------------------------------------------------------------------------------------ 60 | 61 | --Q8) Show the number of orders placed by each customer and sort the result by 62 | -- the number of orders in descending order. 63 | 64 | SELECT CustomerId, COUNT(*) AS Orders 65 | FROM Invoices 66 | GROUP BY CustomerId 67 | ORDER BY Orders DESC 68 | 69 | ------------------------------------------------------------------------------------ 70 | 71 | --Q9) Find the albums with 12 or more tracks. 72 | 73 | SELECT AlbumId, Count(*) AS Ntracks 74 | FROM Tracks 75 | GROUP BY AlbumId 76 | HAVING COUNT (*) >= 12 -------------------------------------------------------------------------------- /C1-SQL_for_Data_Science/SQL_data_science_quiz_3.sql: -------------------------------------------------------------------------------- 1 | --Q1) Using a subquery, find the names of all the tracks for the 2 | -- album "Californication". 3 | 4 | SELECT Name, 5 | AlbumID 6 | FROM Tracks 7 | WHERE AlbumId IN (SELECT AlbumId 8 | FROM Albums 9 | WHERE Title = "Californication"); 10 | 11 | ------------------------------------------------------------------------------------ 12 | -- Q2) Find the total number of invoices for each customer along 13 | -- with the customer's full name, city and email. 14 | 15 | SELECT FirstName, 16 | LastName, 17 | City, 18 | Email, 19 | COUNT(I.CustomerId) AS Invoices 20 | FROM Customers C INNER JOIN Invoices I 21 | ON C.CustomerId = I.CustomerId 22 | GROUP BY C.CustomerId 23 | 24 | ------------------------------------------------------------------------------------ 25 | -- Q3) Retrieve the track name, album, artist, and trackID for 26 | -- all the albums. 27 | 28 | SELECT Tracks.Name, 29 | A.Name AS Artist, 30 | Albums.Title AS Album, 31 | Tracks.TrackId 32 | FROM ((Tracks INNER JOIN Albums 33 | ON Tracks.AlbumId = Albums.AlbumId) 34 | INNER JOIN Artists A 35 | ON A.ArtistId = Albums.ArtistId); 36 | 37 | ------------------------------------------------------------------------------------ 38 | -- Q4) Retrieve a list with the managers last name, and the last 39 | -- name of the employees who report to him or her. 40 | 41 | SELECT M.LastName AS Manager, 42 | E.LastName AS Employee 43 | FROM Employees E INNER JOIN Employees M 44 | ON E.ReportsTo = M.EmployeeID 45 | 46 | ------------------------------------------------------------------------------------ 47 | -- Q5) Find the name and ID of the artists who do not have albums. 48 | 49 | SELECT Name AS Artist, 50 | Artists.ArtistId, 51 | Albums.Title AS Album 52 | FROM Artists 53 | LEFT JOIN Albums 54 | ON Artists.ArtistId = Albums.ArtistId 55 | WHERE Album IS NULL 56 | 57 | ------------------------------------------------------------------------------------ 58 | -- Q6) Use a UNION to create a list of all the employee's & 59 | -- customer's first names and last names ordered by the last 60 | -- name in descending order. 61 | 62 | SELECT FirstName, 63 | LastName 64 | FROM Employees 65 | UNION 66 | SELECT FirstName, 67 | LastName 68 | FROM Customers 69 | ORDER BY LastName DESC 70 | 71 | ------------------------------------------------------------------------------------ 72 | -- Q7) See if there are any customers who have a different city 73 | -- listed in their billing city versus their customer city. 74 | 75 | SELECT C.FirstName, 76 | C.LastName, 77 | C.City AS CustomerCity, 78 | I.BillingCity 79 | FROM Customers C 80 | INNER JOIN Invoices I 81 | ON C.CustomerId = I.CustomerId 82 | WHERE CustomerCity != BillingCity -------------------------------------------------------------------------------- /C1-SQL_for_Data_Science/SQL_data_science_quiz_4.sql: -------------------------------------------------------------------------------- 1 | -- Q1) Pull a list of customer ids with the customer’s full name, and address, 2 | -- along with combining their city and country together. Be sure to make a 3 | -- space in between these two and make it UPPER CASE. 4 | 5 | SELECT CustomerId, 6 | FirstName || " " || LastName AS FullName, 7 | Address, 8 | UPPER(City || " " || Country) AS CityCountry 9 | FROM Customers 10 | 11 | ------------------------------------------------------------------------------------ 12 | -- Q2) Create a new employee user id by combining the first 4 letter of the 13 | -- employee’s first name with the first 2 letters of the employee’s last name. 14 | -- Make the new field lower case and pull each individual step to show your work. 15 | 16 | SELECT FirstName, 17 | LastName, 18 | LOWER(SUBSTR(FirstName,1,4)) AS A, 19 | LOWER(SUBSTR(LastName,1,2)) AS B, 20 | LOWER(SUBSTR(FirstName,1,4)) || LOWER(SUBSTR(LastName,1,2)) AS userId 21 | FROM Employees 22 | 23 | ------------------------------------------------------------------------------------ 24 | -- Q3) Show a list of employees who have worked for the company for 15 or more 25 | -- years using the current date function. Sort by lastname ascending. 26 | 27 | SELECT FirstName, 28 | LastName, 29 | HireDate, 30 | (STRFTIME('%Y', 'now') - STRFTIME('%Y', HireDate)) 31 | - (STRFTIME('%m-%d', 'now') < STRFTIME('%m-%d', HireDate)) 32 | AS YearsWorked 33 | FROM Employees 34 | WHERE YearsWorked >= 15 35 | ORDER BY LastName ASC 36 | 37 | ------------------------------------------------------------------------------------ 38 | -- Q4) Profiling the Customers table, answer the following question. 39 | 40 | SELECT COUNT(*) 41 | FROM Customers 42 | WHERE [some_column] IS NULL 43 | 44 | -- some_column: FirstName, PostalCode, Company, Fax, Phone, Address 45 | -- Answers: Postal Code, Company, Fax, Phone 46 | 47 | ------------------------------------------------------------------------------------ 48 | -- Q5) Find the cities with the most customers and rank in descending order. 49 | 50 | SELECT City, 51 | COUNT(*) 52 | FROM Customers 53 | GROUP BY City 54 | ORDER BY COUNT(*) DESC 55 | 56 | ------------------------------------------------------------------------------------ 57 | -- Q6) Create a new customer invoice id by combining a customer’s invoice id with 58 | -- their first and last name while ordering your query in the following order: 59 | -- firstname, lastname, and invoiceID. 60 | 61 | SELECT C.FirstName, 62 | C.LastName, 63 | I.InvoiceId, 64 | C.FirstName || C.LastName || I.InvoiceID AS NewId 65 | FROM Customers C INNER JOIN Invoices I 66 | ON C.CustomerId = I.CustomerID 67 | WHERE NewId LIKE 'AstridGruber%' -------------------------------------------------------------------------------- /C1-SQL_for_Data_Science/YelpDatabaseSchema.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/urbanclimatefr/Coursera-Learn-SQL-Basics-for-Data-Science/844aaf928966f21e0d6a04a6cb76a2e4dba4c7eb/C1-SQL_for_Data_Science/YelpDatabaseSchema.png -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/AB_Testing_Final_Assignment.sql: -------------------------------------------------------------------------------- 1 | -- AB Testing Final Assignment 2 | -- We are running an experiment at an item-level, which means all users who visit 3 | -- will see the same page, but the layout of different item pages may differ. 4 | 5 | -- Compare this table to the assignment events we captured for user_level_testing. 6 | -- Does this table have everything you need to compute metrics like 30-day view-binary? 7 | -- Answer is No. The created_at date is needed. 8 | 9 | SELECT * 10 | FROM dsv1069.final_assignments_qa; 11 | 12 | -- Write a query and table creation statement to make final_assignments_qa 13 | -- look like the final_assignments table. If you discovered something missing 14 | -- in part 1, you may fill in the value with a place holder of the appropriate 15 | -- data type. 16 | 17 | SELECT item_id, 18 | test_a AS test_assignment, 19 | (CASE 20 | WHEN test_a IS NOT NULL then 'test_a' 21 | ELSE NULL 22 | END) AS test_number, 23 | (CASE 24 | WHEN test_a IS NOT NULL then '2013-01-05 00:00:00' 25 | ELSE NULL 26 | END) AS test_start_date 27 | FROM dsv1069.final_assignments_qa 28 | UNION 29 | SELECT item_id, 30 | test_b AS test_assignment, 31 | (CASE 32 | WHEN test_b IS NOT NULL then 'test_b' 33 | ELSE NULL 34 | END) AS test_number, 35 | (CASE 36 | WHEN test_b IS NOT NULL then '2013-01-05 00:00:00' 37 | ELSE NULL 38 | END) AS test_start_date 39 | FROM dsv1069.final_assignments_qa 40 | UNION 41 | SELECT item_id, 42 | test_c AS test_assignment, 43 | (CASE 44 | WHEN test_c IS NOT NULL then 'test_c' 45 | ELSE NULL 46 | END) AS test_number, 47 | (CASE 48 | WHEN test_c IS NOT NULL then '2013-01-05 00:00:00' 49 | ELSE NULL 50 | END) AS test_start_date 51 | FROM dsv1069.final_assignments_qa 52 | UNION 53 | SELECT item_id, 54 | test_d AS test_assignment, 55 | (CASE 56 | WHEN test_d IS NOT NULL then 'test_d' 57 | ELSE NULL 58 | END) AS test_number, 59 | (CASE 60 | WHEN test_d IS NOT NULL then '2013-01-05 00:00:00' 61 | ELSE NULL 62 | END) AS test_start_date 63 | FROM dsv1069.final_assignments_qa 64 | UNION 65 | SELECT item_id, 66 | test_e AS test_assignment, 67 | (CASE 68 | WHEN test_e IS NOT NULL then 'test_e' 69 | ELSE NULL 70 | END) AS test_number, 71 | (CASE 72 | WHEN test_e IS NOT NULL then '2013-01-05 00:00:00' 73 | ELSE NULL 74 | END) AS test_start_date 75 | FROM dsv1069.final_assignments_qa 76 | UNION 77 | SELECT item_id, 78 | test_f AS test_assignment, 79 | (CASE 80 | WHEN test_f IS NOT NULL then 'test_f' 81 | ELSE NULL 82 | END) AS test_number, 83 | (CASE 84 | WHEN test_f IS NOT NULL then '2013-01-05 00:00:00' 85 | ELSE NULL 86 | END) AS test_start_date 87 | FROM dsv1069.final_assignments_qa; 88 | 89 | -- Use the final_assignments table to calculate the order binary for the 90 | -- 30 day window after the test assignment for item_test_2 (You may include 91 | -- the day the test started) 92 | 93 | SELECT test_assignment, 94 | COUNT(DISTINCT item_id) AS number_of_items, 95 | SUM(order_binary) AS items_ordered_30d 96 | FROM 97 | (SELECT item_test_2.item_id, 98 | item_test_2.test_assignment, 99 | item_test_2.test_number, 100 | item_test_2.test_start_date, 101 | item_test_2.created_at, 102 | MAX(CASE 103 | WHEN (created_at > test_start_date 104 | AND DATE_PART('day', created_at - test_start_date) <= 30) THEN 1 105 | ELSE 0 106 | END) AS order_binary 107 | FROM 108 | (SELECT final_assignments.*, 109 | DATE(orders.created_at) AS created_at 110 | FROM dsv1069.final_assignments AS final_assignments 111 | LEFT JOIN dsv1069.orders AS orders 112 | ON final_assignments.item_id = orders.item_id 113 | WHERE test_number = 'item_test_2') AS item_test_2 114 | GROUP BY item_test_2.item_id, 115 | item_test_2.test_assignment, 116 | item_test_2.test_number, 117 | item_test_2.test_start_date, 118 | item_test_2.created_at) AS order_binary 119 | GROUP BY test_assignment; 120 | 121 | -- Use the final_assignments table to calculate the view binary, and 122 | -- average views for the 30 day window after the test assignment for 123 | -- item_test_2. (You may include the day the test started) 124 | 125 | SELECT item_test_2.item_id, 126 | item_test_2.test_assignment, 127 | item_test_2.test_number, 128 | MAX(CASE 129 | WHEN (view_date > test_start_date 130 | AND DATE_PART('day', view_date - test_start_date) <= 30) THEN 1 131 | ELSE 0 132 | END) AS view_binary 133 | FROM 134 | (SELECT final_assignments.*, 135 | DATE(events.event_time) AS view_date 136 | FROM dsv1069.final_assignments AS final_assignments 137 | LEFT JOIN 138 | (SELECT event_time, 139 | CASE 140 | WHEN parameter_name = 'item_id' THEN CAST(parameter_value AS NUMERIC) 141 | ELSE NULL 142 | END AS item_id 143 | FROM dsv1069.events 144 | WHERE event_name = 'view_item') AS events 145 | ON final_assignments.item_id = events.item_id 146 | WHERE test_number = 'item_test_2') AS item_test_2 147 | GROUP BY item_test_2.item_id, 148 | item_test_2.test_assignment, 149 | item_test_2.test_number 150 | LIMIT 100; 151 | 152 | -- Use the https://thumbtack.github.io/abba/demo/abba.html 153 | -- to compute the lifts in metrics and the p-values for the binary 154 | -- metrics (30 day order binary and 30 day view binary) using a 155 | -- interval 95% confidence. 156 | 157 | SELECT test_assignment, 158 | test_number, 159 | COUNT(DISTINCT item) AS number_of_items, 160 | SUM(view_binary_30d) AS view_binary_30d 161 | FROM 162 | (SELECT final_assignments.item_id AS item, 163 | test_assignment, 164 | test_number, 165 | test_start_date, 166 | MAX((CASE 167 | WHEN date(event_time) - date(test_start_date) BETWEEN 0 AND 30 THEN 1 168 | ELSE 0 169 | END)) AS view_binary_30d 170 | FROM dsv1069.final_assignments 171 | LEFT JOIN dsv1069.view_item_events 172 | ON final_assignments.item_id = view_item_events.item_id 173 | WHERE test_number = 'item_test_2' 174 | GROUP BY final_assignments.item_id, 175 | test_assignment, 176 | test_number, 177 | test_start_date) AS view_binary 178 | GROUP BY test_assignment, 179 | test_number, 180 | test_start_date; 181 | 182 | 183 | -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/Analyze_Test_Results_for_CV.sql: -------------------------------------------------------------------------------- 1 | -- Analyze Test Results for CV 2 | -- Exercise 1 3 | -- Use the order_binary metric from the previous exercise 4 | -- For the proportion metric order binary compute the following: 5 | -- The count of users per treatment group for test_id = 7 6 | -- The count of usrs with orders per treatment group 7 | 8 | SELECT test_assignment, 9 | COUNT(user_id) AS users, 10 | SUM(order_binary) AS users_with_orders 11 | FROM 12 | (SELECT assignments.user_id, 13 | assignments.test_id, 14 | assignments.test_assignment, 15 | MAX(CASE 16 | WHEN orders.created_at > assignments.event_time THEN 1 17 | ELSE 0 18 | END) AS order_binary 19 | FROM 20 | (SELECT event_id, 21 | event_time, 22 | user_id, 23 | MAX(CASE 24 | WHEN parameter_name = 'test_id' THEN CAST(parameter_value AS INT) 25 | ELSE NULL 26 | END) AS test_id, 27 | MAX(CASE 28 | WHEN parameter_name = 'test_assignment' THEN CAST(parameter_value AS INT) 29 | ELSE NULL 30 | END) AS test_assignment 31 | FROM dsv1069.events 32 | GROUP BY event_id, 33 | event_time, 34 | user_id 35 | ORDER BY event_id) assignments 36 | LEFT OUTER JOIN dsv1069.orders 37 | ON assignments.user_id = orders.user_id 38 | GROUP BY assignments.user_id, 39 | assignments.test_id, 40 | assignments.test_assignment) user_level 41 | WHERE test_id = 7 42 | GROUP BY test_assignment; 43 | 44 | -- Exercise 2: Create a new tem view binary metric. Count the number 45 | -- of users per treatment group, and count the number of users 46 | -- with views (for test_id 7) 47 | 48 | SELECT test_assignment, 49 | COUNT(user_id) AS users, 50 | SUM(views_binary) AS views_binary 51 | FROM 52 | (SELECT assignments.user_id, 53 | assignments.test_id, 54 | assignments.test_assignment, 55 | MAX(CASE 56 | WHEN views.event_time > assignments.event_time THEN 1 57 | ELSE 0 58 | END) AS views_binary 59 | FROM 60 | (SELECT event_id, 61 | event_time, 62 | user_id, 63 | MAX(CASE 64 | WHEN parameter_name = 'test_id' THEN CAST(parameter_value AS INT) 65 | ELSE NULL 66 | END) AS test_id, 67 | MAX(CASE 68 | WHEN parameter_name = 'test_assignment' THEN CAST(parameter_value AS INT) 69 | ELSE NULL 70 | END) AS test_assignment 71 | FROM dsv1069.events 72 | GROUP BY event_id, 73 | event_time, 74 | user_id 75 | ORDER BY event_id) assignments 76 | LEFT OUTER JOIN 77 | (SELECT * 78 | FROM dsv1069.events 79 | WHERE event_name = 'view_item' ) views 80 | ON assignments.user_id = views.user_id 81 | GROUP BY assignments.user_id, 82 | assignments.test_id, 83 | assignments.test_assignment) user_level 84 | WHERE test_id = 7 85 | GROUP BY test_assignment; 86 | 87 | -- Exercise 3: Alter the result from EX 2, to compute the users who 88 | -- viewed an item WITHIN 30 days of their treatment event 89 | 90 | SELECT test_assignment, 91 | COUNT(user_id) AS users, 92 | SUM(views_binary) AS views_binary, 93 | SUM(views_binary_30d) AS views_binary_30d 94 | FROM 95 | (SELECT assignments.user_id, 96 | assignments.test_id, 97 | assignments.test_assignment, 98 | MAX(CASE 99 | WHEN views.event_time > assignments.event_time THEN 1 100 | ELSE 0 101 | END) AS views_binary, 102 | MAX(CASE 103 | WHEN (views.event_time > assignments.event_time 104 | AND DATE_PART('day', views.event_time - assignments.event_time) <= 30) THEN 1 105 | ELSE 0 106 | END) AS views_binary_30d 107 | FROM 108 | (SELECT event_id, 109 | event_time, 110 | user_id, 111 | MAX(CASE 112 | WHEN parameter_name = 'test_id' THEN CAST(parameter_value AS INT) 113 | ELSE NULL 114 | END) AS test_id, 115 | MAX(CASE 116 | WHEN parameter_name = 'test_assignment' THEN CAST(parameter_value AS INT) 117 | ELSE NULL 118 | END) AS test_assignment 119 | FROM dsv1069.events 120 | GROUP BY event_id, 121 | event_time, 122 | user_id 123 | ORDER BY event_id) assignments 124 | LEFT OUTER JOIN 125 | (SELECT * 126 | FROM dsv1069.events 127 | WHERE event_name = 'view_item' ) views 128 | ON assignments.user_id = views.user_id 129 | GROUP BY assignments.user_id, 130 | assignments.test_id, 131 | assignments.test_assignment) user_level 132 | WHERE test_id = 7 133 | GROUP BY test_assignment; 134 | 135 | -- Exercise 4: 136 | -- Create the metric invoices (this is a mean metric, not a binary metric) 137 | -- and for test_id = 7 138 | ----The count of users per treatment group 139 | ----The average value of the metric per treatment group 140 | ----The standard deviation of the metric per treatment group 141 | 142 | SELECT test_id, 143 | test_assignment, 144 | COUNT(user_id) AS users, 145 | AVG(invoices) AS avg_invoices, 146 | STDDEV(invoices) AS stddev_invoices 147 | FROM 148 | (SELECT assignments.user_id, 149 | assignments.test_id, 150 | assignments.test_assignment, 151 | COUNT(DISTINCT CASE 152 | WHEN orders.created_at > assignments.event_time THEN orders.invoice_id 153 | ELSE NULL 154 | END) AS invoices, 155 | COUNT(DISTINCT CASE 156 | WHEN orders.created_at > assignments.event_time THEN orders.line_item_id 157 | ELSE NULL 158 | END) AS line_items, 159 | COALESCE(SUM(CASE 160 | WHEN orders.created_at > assignments.event_time THEN orders.price 161 | ELSE 0 162 | END), 0) AS total_revenue 163 | FROM 164 | (SELECT event_id, 165 | event_time, 166 | user_id, 167 | MAX(CASE 168 | WHEN parameter_name = 'test_id' THEN CAST(parameter_value AS INT) 169 | ELSE NULL 170 | END) AS test_id, 171 | MAX(CASE 172 | WHEN parameter_name = 'test_assignment' THEN CAST(parameter_value AS INT) 173 | ELSE NULL 174 | END) AS test_assignment 175 | FROM dsv1069.events 176 | GROUP BY event_id, 177 | event_time, 178 | user_id 179 | ORDER BY event_id) assignments 180 | LEFT OUTER JOIN dsv1069.orders 181 | ON assignments.user_id = orders.user_id 182 | GROUP BY assignments.user_id, 183 | assignments.test_id, 184 | assignments.test_assignment) mean_metrics 185 | GROUP BY test_id, 186 | test_assignment 187 | ORDER BY test_id; 188 | -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/Counting_Users.sql: -------------------------------------------------------------------------------- 1 | -- Counting Users 2 | -- Exercise 1: 3 | -- We’ll be using the users table to answer the question 4 | -- “How many new users are added each day?“. 5 | -- Start by making sure you understand the columns in the table 6 | 7 | -- SELECT * 8 | -- FROM dsv1069.users; 9 | -- created_at 10 | -- deleted_at 11 | -- email_address 12 | -- first_name 13 | -- id 14 | -- last_name 15 | -- merged_at 16 | -- parent_user_id 17 | 18 | -- understand what is going on with the merged at id 19 | -- SELECT id, 20 | -- parent_user_id, 21 | -- merged_at 22 | -- FROM dsv1069.users 23 | -- ORDER BY parent_user_id ASC; 24 | 25 | SELECT DATE(created_at) AS day, 26 | COUNT(*) AS users 27 | FROM dsv1069.users 28 | GROUP BY day 29 | ORDER BY day ASC; 30 | 31 | -- Exercise 2: 32 | -- WIthout worrying about deleted user or merged users, 33 | -- count the number of users added each day. 34 | 35 | -- columns 36 | -- created_at 37 | -- deleted_at 38 | -- email_address 39 | -- first_name 40 | -- id 41 | -- last_name 42 | -- merged_at 43 | -- parent_user_id 44 | 45 | -- SELECT COUNT(id) as num_users 46 | -- FROM dsv1069.users; 47 | -- returns 117,178 users 48 | 49 | SELECT DATE(created_at) AS day, 50 | COUNT(id) as num_users 51 | FROM dsv1069.users 52 | GROUP BY day 53 | ORDER BY day ASC; 54 | 55 | -- Exercise 3: 56 | -- Consider the following query. Is this the right way to count 57 | -- merged or deleted users? 58 | -- If all of our users were deleted tomorrow what would the result look like? 59 | 60 | 61 | -- columns 62 | -- created_at 63 | -- deleted_at 64 | -- email_address 65 | -- first_name 66 | -- id 67 | -- last_name 68 | -- merged_at 69 | -- parent_user_id 70 | 71 | -- SELECT COUNT(id) as num_users 72 | -- FROM dsv1069.users; 73 | -- returns 117,178 users 74 | 75 | -- SELECT DATE(created_at) AS date_created, 76 | -- COUNT(id) as num_users 77 | -- FROM dsv1069.users 78 | -- GROUP BY date_created 79 | -- ORDER BY date_created ASC; 80 | 81 | SELECT DATE(created_at) AS day, 82 | COUNT(*) AS users 83 | FROM dsv1069.users 84 | WHERE deleted_at IS NULL 85 | AND (id <> parent_user_id OR parent_user_id IS NULL) 86 | GROUP BY day; 87 | 88 | -- Exercise 4: 89 | -- Count the number of users deleted each day. Then count the number of users 90 | -- removed due to merging in a similar way. 91 | 92 | 93 | 94 | -- columns 95 | -- created_at 96 | -- deleted_at 97 | -- email_address 98 | -- first_name 99 | -- id 100 | -- last_name 101 | -- merged_at 102 | -- parent_user_id 103 | 104 | -- SELECT COUNT(id) as num_users 105 | -- FROM dsv1069.users; 106 | -- returns 117,178 users 107 | 108 | -- SELECT DATE(created_at) AS date_created, 109 | -- COUNT(id) as num_users 110 | -- FROM dsv1069.users 111 | -- GROUP BY date_created 112 | -- ORDER BY date_created ASC; 113 | 114 | -- SELECT COUNT(*) AS users 115 | -- FROM dsv1069.users 116 | -- WHERE deleted_at IS NOT NULL 117 | -- returns 2,888 users 118 | 119 | SELECT DATE(created_at) AS day, 120 | COUNT(*) AS users 121 | FROM dsv1069.users 122 | WHERE deleted_at IS NOT NULL 123 | GROUP BY day; 124 | 125 | -- Exercise 5: 126 | -- Use the pieces you’ve built as subtables and create a table that has a column for 127 | -- the date, the number of users created, the number of users deleted and 128 | -- the number of users merged that day. 129 | 130 | -- columns 131 | -- created_at 132 | -- deleted_at 133 | -- email_address 134 | -- first_name 135 | -- id 136 | -- last_name 137 | -- merged_at 138 | -- parent_user_id 139 | 140 | SELECT new.day, 141 | new.new_added_users, 142 | COALESCE(deleted.deleted_users, 0) AS deleted_users, 143 | COALESCE(merged.merged_users, 0) AS merged_users, 144 | (new.new_added_users - COALESCE(deleted.deleted_users, 0) - COALESCE(merged.merged_users, 0)) 145 | AS net_added_users 146 | FROM (SELECT DATE(created_at) AS day, 147 | COUNT(*) AS new_added_users 148 | FROM dsv1069.users 149 | GROUP BY day) new 150 | LEFT JOIN 151 | (SELECT DATE(created_at) AS day, 152 | COUNT(*) AS deleted_users 153 | FROM dsv1069.users 154 | WHERE deleted_at IS NOT NULL 155 | GROUP BY day) deleted 156 | ON deleted.day = new.day 157 | LEFT JOIN 158 | (SELECT DATE(merged_at) AS day, 159 | COUNT(*) AS merged_users 160 | FROM dsv1069.users 161 | WHERE id <> parent_user_id 162 | AND parent_user_id IS NOT NULL 163 | GROUP BY day) merged 164 | ON merged.day = new.day 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/Create_a_Rollup_Table.sql: -------------------------------------------------------------------------------- 1 | -- Create a Rollup Table 2 | -- Exercise 1: 3 | -- Create a subtable of orders per day. Make sure you decide 4 | -- whether you are counting invoices or line items. 5 | -- SELECT * 6 | -- FROM dsv1069.orders 7 | 8 | SELECT DATE(paid_at) AS day, 9 | COUNT(DISTINCT invoice_id) AS orders, 10 | COUNT(DISTINCT line_item_id) AS line_items 11 | FROM dsv1069.orders 12 | GROUP BY day 13 | ORDER BY day ASC; 14 | 15 | -- Exercise 2: 16 | -- “Check your joins”. We are still trying to count orders per day. 17 | -- In this step join the sub table from the previous exercise to 18 | -- the dates rollup table so we can get a row for every date. Check 19 | -- that the join works by just running a “select *” query 20 | 21 | SELECT * 22 | FROM dsv1069.dates_rollup 23 | LEFT OUTER JOIN 24 | (SELECT DATE(paid_at) AS day, 25 | COUNT(DISTINCT invoice_id) AS orders, 26 | COUNT(DISTINCT line_item_id) AS line_items 27 | FROM dsv1069.orders 28 | GROUP BY day) daily_orders 29 | ON daily_orders.day = dates_rollup.date; 30 | 31 | -- Exercise 3: 32 | -- “Clean up your Columns” In this step be sure to specify the columns 33 | -- you actually want to return, and if necessary do any aggregation 34 | -- needed to get a count of the orders made per day 35 | 36 | SELECT dates_rollup.date, 37 | COALESCE(SUM(orders), 0) AS orders, 38 | COALESCE(SUM(items_ordered), 0) AS items_ordered 39 | FROM dsv1069.dates_rollup 40 | LEFT OUTER JOIN 41 | (SELECT DATE(paid_at) AS day, 42 | COUNT(DISTINCT invoice_id) AS orders, 43 | COUNT(DISTINCT line_item_id) AS items_ordered 44 | FROM dsv1069.orders 45 | GROUP BY day) daily_orders 46 | ON daily_orders.day = dates_rollup.date 47 | GROUP BY dates_rollup.date; 48 | 49 | -- Exercise 4: 50 | -- Weekly Rollup. Figure out which parts of the JOIN condition need 51 | -- to be edited create 7 day rolling orders table. 52 | 53 | SELECT * 54 | FROM dsv1069.dates_rollup 55 | LEFT OUTER JOIN 56 | (SELECT DATE(orders.paid_at) AS day, 57 | COUNT(DISTINCT invoice_id) AS orders, 58 | COUNT(DISTINCT line_item_id) AS items_ordered 59 | FROM dsv1069.orders 60 | GROUP BY DATE(orders.paid_at)) daily_orders 61 | ON dates_rollup.date >= daily_orders.day 62 | AND dates_rollup.d7_ago < daily_orders.day 63 | 64 | -- Exercise 5: 65 | -- Column Cleanup. Finish creating the weekly rolling orders table, 66 | -- by performing any aggregation steps and naming your columns appropriately. 67 | 68 | SELECT dates_rollup.date, 69 | COALESCE(SUM(orders), 0) AS orders, 70 | COALESCE(SUM(items_ordered), 0) AS items_ordered, 71 | COUNT(*) AS rows 72 | FROM dsv1069.dates_rollup 73 | LEFT OUTER JOIN 74 | (SELECT DATE(orders.paid_at) AS day, 75 | COUNT(DISTINCT invoice_id) AS orders, 76 | COUNT(DISTINCT line_item_id) AS items_ordered 77 | FROM dsv1069.orders 78 | GROUP BY DATE(orders.paid_at)) daily_orders 79 | ON dates_rollup.date >= daily_orders.day 80 | AND dates_rollup.d7_ago < daily_orders.day 81 | GROUP BY dates_rollup.date 82 | 83 | 84 | -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/Create_a_Test_Metric.sql: -------------------------------------------------------------------------------- 1 | -- Create a Test Metric 2 | -- Exercise 1: 3 | -- Using the table from Exercise 4.3 and compute a metric that measures 4 | -- whether a user created an order after their test assignment 5 | -- Requirements: Even if a user had zero orders, we should have a row 6 | -- that counts their number of orders as zero 7 | -- If the user is not in the experiment they should not be included 8 | 9 | SELECT test_events.test_id, 10 | test_events.test_assignment, 11 | test_events.user_id, 12 | MAX(CASE 13 | WHEN orders.created_at > test_events.event_time THEN 1 14 | ELSE 0 15 | END) AS orders_after_assignment_binary 16 | FROM 17 | ( SELECT event_id, 18 | event_time, 19 | user_id, -- platform, 20 | MAX(CASE 21 | WHEN parameter_name = 'test_id' THEN CAST(parameter_value AS INT) 22 | ELSE NULL 23 | END) AS test_id, 24 | MAX(CASE 25 | WHEN parameter_name = 'test_assignment' THEN CAST(parameter_value AS INT) 26 | ELSE NULL 27 | END) AS test_assignment 28 | FROM dsv1069.events 29 | WHERE event_name = 'test_assignment' 30 | GROUP BY event_id, 31 | event_time, 32 | user_id ) test_events 33 | LEFT JOIN dsv1069.orders 34 | ON orders.user_id = test_events.user_id 35 | GROUP BY test_events.test_id, 36 | test_events.test_assignment, 37 | test_events.user_id; 38 | 39 | -- Exercise 2: 40 | -- Using the table from the previous exercise, add the following metrics 41 | -- 1) the number of orders/invoices 42 | -- 2) the number of items/line-items ordered 43 | -- 3) the total revenue from the order after treatment 44 | 45 | SELECT test_events.test_id, 46 | test_events.test_assignment, 47 | test_events.user_id, 48 | COUNT(DISTINCT (CASE 49 | WHEN orders.created_at > test_events.event_time THEN invoice_id 50 | ELSE NULL 51 | END)) AS orders_after_assignment, 52 | COUNT(DISTINCT (CASE 53 | WHEN orders.created_at > test_events.event_time THEN line_item_id 54 | ELSE NULL 55 | END)) AS items_after_assignment, 56 | SUM((CASE 57 | WHEN orders.created_at > test_events.event_time THEN price 58 | ELSE 0 59 | END)) AS total_revenue 60 | FROM 61 | (SELECT event_id, 62 | event_time, 63 | user_id, -- platform, 64 | MAX(CASE 65 | WHEN parameter_name = 'test_id' THEN CAST(parameter_value AS INT) 66 | ELSE NULL 67 | END) AS test_id, 68 | MAX(CASE 69 | WHEN parameter_name = 'test_assignment' THEN CAST(parameter_value AS INT) 70 | ELSE NULL 71 | END) AS test_assignment 72 | FROM dsv1069.events 73 | WHERE event_name = 'test_assignment' 74 | GROUP BY event_id, 75 | event_time, 76 | user_id ) test_events 77 | LEFT JOIN dsv1069.orders 78 | ON orders.user_id = test_events.user_id 79 | GROUP BY test_events.test_id, 80 | test_events.test_assignment, 81 | test_events.user_id; 82 | 83 | -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/Error_Codes.sql: -------------------------------------------------------------------------------- 1 | -- Exercise 1: 2 | -- Goal: Here we use users table to pull a list of user email addresses. 3 | -- Edit the query to pull email addresses, but only for non-deleted users. 4 | 5 | SELECT email_address 6 | 7 | FROM dsv1069.users 8 | 9 | WHERE deleted_at is NULL; 10 | 11 | -- Exercise 2: 12 | -- Goal: Use the items table to count the number of items for sale in each category 13 | 14 | SELECT category, 15 | COUNT(id) AS item_count 16 | 17 | FROM dsv1069.items 18 | 19 | GROUP BY category 20 | 21 | ORDER BY item_count ASC; 22 | 23 | -- Exercise 3: 24 | --Goal: Select all of the columns from the result when you JOIN the users 25 | -- table to the orders table 26 | 27 | SELECT * 28 | 29 | FROM dsv1069.users u 30 | 31 | JOIN dsv1069.orders o 32 | ON u.id = o.user_id 33 | 34 | ORDER BY u.id ASC; 35 | 36 | -- Exercise 4: 37 | --Goal: Check out the query below. This is not the right way to count the 38 | -- number of viewed_item events. Determine what is wrong and correct the error. 39 | 40 | SELECT COUNT(DISTINCT event_id) AS events 41 | 42 | FROM dsv1069.events 43 | 44 | WHERE event_name = 'view_item'; 45 | 46 | -- Exercise 5: 47 | --Goal:Compute the number of items in the items table which have been 48 | -- ordered. The query below runs, but it isn’t right. Determine what is 49 | -- wrong and correct the error or start from scratch. 50 | 51 | SELECT COUNT(DISTINCT o.item_id) AS item_count 52 | 53 | FROM dsv1069.orders o; 54 | 55 | -- Exercise 6: 56 | --Goal: For each user figure out IF a user has ordered something, and 57 | -- when their first purchase was. The query below doesn’t return info 58 | -- for any of the users who haven’t ordered anything. 59 | 60 | SELECT users.id as user_id, 61 | MIN(orders.paid_at) AS min_paid_at 62 | 63 | FROM dsv1069.users 64 | 65 | LEFT JOIN dsv1069.orders 66 | ON users.id = orders.user_id 67 | 68 | GROUP BY users.id 69 | 70 | ORDER BY min_paid_at DESC; 71 | 72 | -- Exercise 7: 73 | --Goal: Figure out what percent of users have ever viewed the user 74 | -- profile page, but this query isn’t right. Check to make sure the 75 | -- number of users adds up, and if not, fix the query. 76 | 77 | SELECT ( 78 | CASE 79 | WHEN first_view IS NULL 80 | THEN false 81 | ELSE true 82 | END 83 | ) AS has_viewed_profile_page, 84 | COUNT(user_id) AS users 85 | 86 | -- creates first_profile_views table 87 | FROM ( 88 | SELECT users.id AS user_id, 89 | MIN(event_time) AS first_view 90 | 91 | FROM dsv1069.users 92 | 93 | LEFT JOIN dsv1069.events 94 | ON events.user_id = users.id 95 | AND event_name = 'view_user_profile' 96 | 97 | GROUP BY users.id 98 | ) first_profile_views 99 | 100 | GROUP BY has_viewed_profile_page; 101 | 102 | -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/Flexible_Data_Formats.sql: -------------------------------------------------------------------------------- 1 | -- Flexible Data Formats 2 | 3 | -- Exercise 1: 4 | -- Goal: Write a query to format the view_item event into a table with the appropriate columns 5 | 6 | SELECT event_id, 7 | event_time, 8 | user_id, 9 | platform, 10 | parameter_name, 11 | parameter_value 12 | FROM dsv1069.events 13 | 14 | WHERE event_name = 'view_item' 15 | 16 | ORDER BY event_id; 17 | 18 | -- Exercise 2: 19 | -- Goal: Write a query to format the view_item event into a table with the appropriate columns 20 | -- (This replicates what we had in the slides, but it is missing a column) 21 | 22 | SELECT event_id, 23 | event_time, 24 | user_id, 25 | platform, 26 | ( 27 | CASE 28 | WHEN parameter_name = 'item_id' 29 | THEN CAST(parameter_value AS INT) 30 | ELSE NULL 31 | END 32 | ) AS item_id, 33 | ( 34 | CASE 35 | WHEN parameter_name = 'referrer' 36 | THEN parameter_value 37 | ELSE NULL 38 | END 39 | ) AS referrer 40 | 41 | FROM dsv1069.events 42 | 43 | WHERE event_name = 'view_item' 44 | 45 | ORDER BY event_id; 46 | 47 | --Exercise 3: 48 | -- Goal: Use the result from the previous exercise, but make sure 49 | SELECT event_id, 50 | event_time, 51 | user_id, 52 | platform, 53 | MAX(CASE 54 | WHEN parameter_name = 'item_id' 55 | THEN CAST(parameter_value AS INT) 56 | ELSE NULL 57 | END) AS item_id, 58 | MAX(CASE 59 | WHEN parameter_name = 'referrer' 60 | THEN parameter_value 61 | ELSE NULL 62 | END) AS referrer 63 | 64 | FROM dsv1069.events 65 | 66 | WHERE event_name = 'view_item' 67 | 68 | GROUP BY event_id, 69 | event_time, 70 | user_id, 71 | platform 72 | 73 | ORDER BY event_id; 74 | -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/Identifying_Unreliable_Data_Nulls.sql: -------------------------------------------------------------------------------- 1 | -- Identifying Unreliable Data + Nulls 2 | -- Exercise 1: Using any methods you like determine if you can 3 | -- you trust this events table. 4 | 5 | -- review the columns in the table 6 | -- SELECT * 7 | -- FROM dsv1069.events_201701 8 | -- LIMIT 5; 9 | -- event_id 10 | -- event_time 11 | -- user_id 12 | -- event_name 13 | -- platform 14 | -- parameter_name 15 | -- parameter_value 16 | 17 | 18 | -- count the number of records 19 | -- SELECT COUNT(*) 20 | -- FROM dsv1069.events_201701 21 | -- LIMIT 5; 22 | -- returns 7,301 records 23 | 24 | -- GROUP BY check 25 | -- SELECT event_name, 26 | -- COUNT(*) 27 | -- FROM dsv1069.events_201701 28 | -- GROUP BY event_name; 29 | -- event_name count 30 | -- test_assignment 3112 31 | -- view_user_profile 197 32 | -- view_item 3992 33 | 34 | SELECT date(event_time) AS date, 35 | COUNT(*) 36 | FROM dsv1069.events_201701 37 | GROUP BY date(event_time); 38 | 39 | 40 | -- NULL check 41 | -- SELECT COUNT(*) 42 | -- FROM dsv1069.events_201701 43 | -- WHERE event_time IS NULL 44 | -- OR user_id IS NULL 45 | -- OR event_name IS NULL 46 | -- OR platform IS NULL 47 | -- OR parameter_name IS NULL 48 | -- OR parameter_value IS NULL; 49 | 50 | -- MIN/MAX/AVG check 51 | -- SELECT MIN(Stars) AS min_val, 52 | -- MAX(Stars) AS max_val, 53 | -- AVG(Stars) AS avg_val 54 | -- FROM review; 55 | 56 | -- Exercise 2: 57 | -- Using any methods you like, determine if you can you trust this 58 | -- events table. (HINT: When did we start recording events on mobile) 59 | 60 | -- get columns 61 | -- SELECT * 62 | -- FROM dsv1069.events_ex2 63 | -- LIMIT 5; 64 | -- event_id 65 | -- event_time 66 | -- user_id 67 | -- event_name 68 | -- platform 69 | -- parameter_name 70 | -- parameter_value 71 | 72 | 73 | -- SELECT platform, 74 | -- COUNT(*) 75 | -- FROM dsv1069.events_ex2 76 | -- GROUP BY platform; 77 | 78 | -- SELECT platform, 79 | -- MIN(event_time) AS first_event_time 80 | -- FROM dsv1069.events_ex2 81 | -- GROUP BY platform; 82 | 83 | -- SELECT DATE(event_time) AS date, 84 | -- COUNT(*) 85 | -- FROM dsv1069.events_ex2 86 | -- GROUP BY DATE(event_time); 87 | 88 | -- SELECT DATE(event_time) AS date, 89 | -- event_name, 90 | -- COUNT(*) 91 | -- FROM dsv1069.events_ex2 92 | -- GROUP BY DATE(event_time), 93 | -- event_name; 94 | 95 | SELECT DATE(event_time) AS date, 96 | platform, 97 | COUNT(*) 98 | FROM dsv1069.events_ex2 99 | GROUP BY DATE(event_time), 100 | platform; 101 | 102 | 103 | -- Exercise 3: Imagine that you need to count item views by day. You found this table 104 | -- item_views_by_category_temp - should you use it to answer your questiuon? 105 | 106 | -- get columns 107 | -- SELECT * 108 | -- FROM dsv1069.item_views_by_category_temp 109 | -- category 110 | -- users 111 | -- view_events 112 | 113 | -- SELECT SUM(view_events) AS event_count 114 | -- FROM dsv1069.item_views_by_category_temp; 115 | 116 | SELECT COUNT(DISTINCT event_id) AS event_count 117 | FROM dsv1069.events 118 | WHERE event_name = 'view_item'; 119 | 120 | -- Exercise 4: 121 | -- Using any methods you like, decide if this table is ready to be 122 | -- used as a source of truth. 123 | 124 | 125 | -- get columns 126 | -- SELECT * 127 | -- FROM dsv1069.events; 128 | -- event_id 129 | -- event_time 130 | -- user_id 131 | -- event_name 132 | -- platform 133 | -- parameter_name 134 | -- parameter_value 135 | 136 | -- SELECT DATE(event_time) AS date, 137 | -- COUNT(*) AS row_count, 138 | -- COUNT(event_id) AS event_count, 139 | -- COUNT(user_id) AS user_count 140 | -- FROM dsv1069.events 141 | -- GROUP BY date; 142 | 143 | SELECT DATE(event_time) AS date, 144 | platform, 145 | COUNT(user_id) AS users 146 | 147 | FROM dsv1069.events 148 | 149 | GROUP BY date, 150 | platform; 151 | 152 | 153 | 154 | -- Exercise 5: 155 | -- Is this the right way to join orders to users? Is this the right way this join. 156 | 157 | -- get columns 158 | -- SELECT * 159 | -- FROM dsv1069.orders 160 | -- LIMIT 100; 161 | -- invoice_id 162 | -- line_item_id 163 | -- user_id 164 | -- item_id 165 | -- item_name 166 | -- item_category 167 | -- price 168 | -- created_at 169 | -- paid_at 170 | 171 | -- get columns 172 | -- SELECT * 173 | -- FROM dsv1069.users 174 | -- LIMIT 100; 175 | -- created_at 176 | -- deleted_at 177 | -- email_address 178 | -- first_name 179 | -- id 180 | -- last_name 181 | -- merged_at 182 | -- parent_user_id 183 | 184 | SELECT COUNT(*) 185 | FROM dsv1069.orders 186 | JOIN dsv1069.users 187 | ON orders.user_id = COALESCE(users.parent_user_id, user_id) 188 | -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/Product_Analysis.sql: -------------------------------------------------------------------------------- 1 | -- Product Analysis 2 | -- Exercise 0: 3 | -- Count how many users we have 4 | 5 | SELECT COUNT(ID) AS id_count 6 | FROM dsv1069.users; 7 | 8 | -- Exercise 1: 9 | -- Find out how many users have ever ordered 10 | 11 | SELECT COUNT(DISTINCT user_id) AS count_users_ordered 12 | FROM dsv1069.orders; 13 | 14 | -- Exercise 2: 15 | -- Goal find how many users have reordered the same item 16 | 17 | -- SELECT * 18 | -- FROM dsv1069.orders 19 | -- LIMIT 100; 20 | -- returns columns: 21 | -- invoice_id 22 | -- line_item_id 23 | -- user_id 24 | -- item_id 25 | -- item_name 26 | -- item_category 27 | -- price 28 | -- created_at 29 | -- paid_at 30 | 31 | SELECT COUNT(DISTINCT user_id) AS users_who_reordered 32 | FROM 33 | ( SELECT user_id, 34 | item_id, 35 | COUNT (DISTINCT line_item_id) AS times_user_ordered 36 | FROM dsv1069.orders 37 | GROUP BY user_id, 38 | item_id ) user_level_orders 39 | WHERE times_user_ordered > 1; 40 | 41 | -- Exercise 3: 42 | -- Do users even order more than once? 43 | -- SELECT * 44 | -- FROM dsv1069.orders 45 | -- LIMIT 100; 46 | -- returns columns: 47 | -- invoice_id 48 | -- line_item_id 49 | -- user_id 50 | -- item_id 51 | -- item_name 52 | -- item_category 53 | -- price 54 | -- created_at 55 | -- paid_at 56 | 57 | SELECT COUNT(DISTINCT user_id) 58 | FROM 59 | ( SELECT user_id, 60 | COUNT(DISTINCT invoice_id) AS order_count 61 | FROM dsv1069.orders 62 | GROUP BY user_id ) user_level 63 | WHERE order_count > 1; 64 | 65 | -- Exercise 4: 66 | -- Orders per item 67 | -- SELECT * 68 | -- FROM dsv1069.orders 69 | -- LIMIT 100; 70 | -- returns columns: 71 | -- invoice_id 72 | -- line_item_id 73 | -- user_id 74 | -- item_id 75 | -- item_name 76 | -- item_category 77 | -- price 78 | -- created_at 79 | -- paid_at 80 | 81 | SELECT item_id, 82 | COUNT(line_item_id) AS times_ordered 83 | FROM dsv1069.orders 84 | GROUP BY item_id 85 | ORDER BY times_ordered DESC; 86 | 87 | -- Exercise 5: 88 | -- Orders per category 89 | 90 | -- SELECT * -- FROM dsv1069.orders 91 | -- LIMIT 100; 92 | -- returns columns: 93 | -- invoice_id 94 | -- line_item_id 95 | -- user_id 96 | -- item_id 97 | -- item_name 98 | -- item_category 99 | -- price 100 | -- created_at 101 | -- paid_at 102 | 103 | SELECT item_category, 104 | COUNT(line_item_id) AS times_ordered 105 | FROM dsv1069.orders 106 | GROUP BY item_category 107 | ORDER BY times_ordered DESC; 108 | 109 | -- Exercise 6: 110 | -- Goal: Do user order multiple things from the same category? 111 | 112 | -- SELECT * 113 | -- FROM dsv1069.orders 114 | -- LIMIT 100; 115 | -- returns columns: 116 | -- invoice_id 117 | -- line_item_id 118 | -- user_id 119 | -- item_id 120 | -- item_name 121 | -- item_category 122 | -- price 123 | -- created_at 124 | -- paid_at 125 | 126 | SELECT item_category, 127 | AVG(times_category_ordered) AS avg_times_category_ordered 128 | FROM 129 | (SELECT user_id, 130 | item_category, 131 | COUNT(DISTINCT line_item_id) AS times_category_ordered 132 | FROM dsv1069.orders 133 | GROUP BY user_id, 134 | item_category) user_level 135 | GROUP BY item_category 136 | 137 | -- Exercise 7: 138 | -- Goal: Find the average time between orders 139 | -- Decide if this analysis is necessary 140 | 141 | SELECT first_orders.user_id, 142 | DATE(first_orders.paid_at) AS first_order_date, 143 | DATE(second_orders.paid_at) AS second_order_date, 144 | DATE(second_orders.paid_at) - DATE(first_orders.paid_at) AS date_diff 145 | FROM 146 | (SELECT user_id, 147 | invoice_id, 148 | paid_at, 149 | DENSE_RANK() OVER (PARTITION BY user_id 150 | ORDER BY paid_at ASC) AS order_num 151 | FROM dsv1069.orders) first_orders 152 | JOIN 153 | (SELECT user_id, 154 | invoice_id, 155 | paid_at, 156 | DENSE_RANK() OVER (PARTITION BY user_id 157 | ORDER BY paid_at ASC) AS order_num 158 | FROM dsv1069.orders) second_orders 159 | ON first_orders.user_id = second_orders.user_id 160 | WHERE first_orders.order_num = 1 161 | AND second_orders.order_num = 2; -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/Promo_Email.sql: -------------------------------------------------------------------------------- 1 | -- Promo Email 2 | -- Exercise 1: 3 | -- Create the right subtable for recently viewed events using 4 | -- the view_item_events table. 5 | 6 | SELECT user_id, 7 | item_id, 8 | event_time, 9 | ROW_NUMBER() OVER (PARTITION BY user_id 10 | ORDER BY event_time DESC) AS row_number, 11 | RANK() OVER (PARTITION BY user_id 12 | ORDER BY event_time DESC) AS rank, 13 | DENSE_RANK() OVER (PARTITION BY user_id 14 | ORDER BY event_time DESC) AS dense_rank 15 | FROM dsv1069.view_item_events 16 | 17 | -- Exercise 2: Check your joins. Join your tables together recent_views, 18 | -- users, items 19 | 20 | -- SELECT * 21 | -- FROM 22 | -- ( 23 | -- SELECT user_id, 24 | -- item_id, 25 | -- event_time, 26 | -- ROW_NUMBER() OVER (PARTITION BY user_id 27 | -- ORDER BY event_time DESC) AS view_number 28 | -- FROM dsv1069.view_item_events 29 | -- ) recent_views 30 | -- JOIN dsv1069.users 31 | -- ON user_id = recent_views.user_id 32 | 33 | SELECT * 34 | FROM 35 | ( 36 | SELECT user_id, 37 | item_id, 38 | event_time, 39 | ROW_NUMBER() OVER (PARTITION BY user_id 40 | ORDER BY event_time DESC) AS view_number 41 | FROM dsv1069.view_item_events 42 | ) recent_views 43 | JOIN dsv1069.users 44 | ON user_id = recent_views.user_id 45 | JOIN dsv1069.items 46 | ON items.id = recent_views.item_id 47 | 48 | -- Exercise 3: Clean up your columns. The goal of all this is to 49 | -- return all of the information we’ll need to send users an email 50 | -- about the item they viewed more recently. Clean up this query 51 | -- outline from the outline in EX2 and pull only the columns you 52 | -- need. Make sure they are named appropriately so that another 53 | -- human can read and understand their contents. 54 | 55 | SELECT users.id AS user_id, 56 | users.email_address, 57 | items.id AS item_id, 58 | items.name AS item_name, 59 | items.category AS item_category 60 | FROM 61 | ( 62 | SELECT user_id, 63 | item_id, 64 | event_time, 65 | ROW_NUMBER() OVER (PARTITION BY user_id 66 | ORDER BY event_time DESC) AS view_number 67 | FROM dsv1069.view_item_events 68 | ) recent_views 69 | JOIN dsv1069.users 70 | ON user_id = recent_views.user_id 71 | JOIN dsv1069.items 72 | ON items.id = recent_views.item_id 73 | 74 | -- Exercise 4: Consider any edge cases. If we sent an email to 75 | -- everyone in the results of this query, what would we want to 76 | -- filter out. Add in any extra filtering that you think would 77 | -- make this email better. For example should we include deleted 78 | -- users? Should we send this email to users who already ordered 79 | -- the item they viewed most recently? 80 | 81 | SELECT COALESCE(users.parent_user_id, users.id) AS user_id, 82 | users.email_address, 83 | items.id AS item_id, 84 | items.name AS item_name, 85 | items.category AS item_category 86 | FROM 87 | ( SELECT user_id, 88 | item_id, 89 | event_time, 90 | ROW_NUMBER() OVER (PARTITION BY user_id 91 | ORDER BY event_time DESC) AS view_number 92 | FROM dsv1069.view_item_events 93 | WHERE event_time > '2017-01-01' ) recent_views 94 | JOIN dsv1069.users 95 | ON user_id = recent_views.user_id 96 | JOIN dsv1069.items 97 | ON items.id = recent_views.item_id 98 | LEFT OUTER JOIN dsv1069.orders 99 | ON orders.item_id = recent_views.item_id 100 | AND orders.user_id = recent_views.user_id 101 | WHERE view_number = 1 102 | AND users.deleted_at IS NOT NULL 103 | AND orders.item_id IS NULL 104 | 105 | -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/README.md: -------------------------------------------------------------------------------- 1 | # Data_Wrangling_Analysis_and_AB_Testing_with_SQL 2 | Data Wrangling, Analysis and AB Testing with SQL 3 | 4 | This course allows you to apply the SQL skills taught in “SQL for Data Science” to four increasingly complex and authentic data science inquiry case studies. We'll learn how to convert timestamps of all types to common formats and perform date/time calculations. We'll select and perform the optimal JOIN for a data science inquiry and clean data within an analysis dataset by deduping, running quality checks, backfilling, and handling nulls. We'll learn how to segment and analyze data per segment using windowing functions and use case statements to execute conditional logic to address a data science inquiry. We'll also describe how to convert a query into a scheduled job and how to insert data into a date partition. Finally, given a predictive analysis need, we'll engineer a feature from raw data using the tools and skills we've built over the course. The real-world application of these skills will give you the framework for performing the analysis of an AB test. 5 | -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/Test_Assignments.sql: -------------------------------------------------------------------------------- 1 | -- Test Assignments 2 | -- Exercise 1: 3 | -- Figure out how many tests we have running right now 4 | 5 | SELECT DISTINCT parameter_value AS test_id 6 | FROM dsv1069.events 7 | WHERE event_name = 'test_assignment' 8 | AND parameter_name = 'test_id'; 9 | 10 | -- Exercise 2: 11 | -- Check for potential problems with test assignments. 12 | -- For example Make sure there is no data obviously missing 13 | -- (This is an open ended question) 14 | 15 | SELECT parameter_value AS test_id, 16 | DATE(event_time) AS day, 17 | COUNT(*) AS event_rows 18 | FROM dsv1069.events 19 | WHERE event_name = 'test_assignment' 20 | AND parameter_name = 'test_id' 21 | GROUP BY parameter_value, 22 | DATE(event_time); 23 | 24 | -- Exercise 3: 25 | -- Write a query that returns a table of assignment events. 26 | -- Please include all of the relevant parameters as columns 27 | -- (Hint: A previous exercise as a template) 28 | 29 | SELECT event_id, 30 | event_time, 31 | user_id, 32 | platform, 33 | MAX(CASE 34 | WHEN parameter_name = 'test_id' THEN CAST(parameter_value AS INT) 35 | ELSE NULL 36 | END) AS test_id, 37 | MAX(CASE 38 | WHEN parameter_name = 'test_assignment' THEN parameter_value 39 | ELSE NULL 40 | END) AS test_assignment 41 | FROM dsv1069.events 42 | WHERE event_name = 'test_assignment' 43 | GROUP BY event_id, 44 | event_time, 45 | user_id, 46 | platform 47 | ORDER BY event_id 48 | 49 | -- Exercise 4: 50 | -- Check for potential assignment problems with test_id 5. 51 | -- Specifically, make sure users are assigned only one treatment group. 52 | 53 | SELECT test_id, 54 | user_id, 55 | COUNT(DISTINCT test_assignment) AS assignments 56 | FROM 57 | (SELECT event_id, 58 | event_time, 59 | user_id, 60 | platform, 61 | MAX(CASE 62 | WHEN parameter_name = 'test_id' THEN CAST(parameter_value AS INT) 63 | ELSE NULL 64 | END) AS test_id, 65 | MAX(CASE 66 | WHEN parameter_name = 'test_assignment' THEN parameter_value 67 | ELSE NULL 68 | END) AS test_assignment 69 | FROM dsv1069.events 70 | WHERE event_name = 'test_assignment' 71 | GROUP BY event_id, 72 | event_time, 73 | user_id, 74 | platform 75 | ORDER BY event_id) test_events 76 | GROUP BY test_id, 77 | user_id 78 | ORDER BY assignments DESC; 79 | 80 | -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/week_1/Connecting-to-Mode.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/urbanclimatefr/Coursera-Learn-SQL-Basics-for-Data-Science/844aaf928966f21e0d6a04a6cb76a2e4dba4c7eb/C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/week_1/Connecting-to-Mode.pdf -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/week_1/Counting-Users.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/urbanclimatefr/Coursera-Learn-SQL-Basics-for-Data-Science/844aaf928966f21e0d6a04a6cb76a2e4dba4c7eb/C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/week_1/Counting-Users.pdf -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/week_1/Error-Codes.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/urbanclimatefr/Coursera-Learn-SQL-Basics-for-Data-Science/844aaf928966f21e0d6a04a6cb76a2e4dba4c7eb/C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/week_1/Error-Codes.pdf -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/week_1/Flexible-Data-Formats.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/urbanclimatefr/Coursera-Learn-SQL-Basics-for-Data-Science/844aaf928966f21e0d6a04a6cb76a2e4dba4c7eb/C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/week_1/Flexible-Data-Formats.pdf -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/week_1/Identifying-Unreliable-Data-_-Nulls.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/urbanclimatefr/Coursera-Learn-SQL-Basics-for-Data-Science/844aaf928966f21e0d6a04a6cb76a2e4dba4c7eb/C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/week_1/Identifying-Unreliable-Data-_-Nulls.pdf -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/week_1/sol.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/urbanclimatefr/Coursera-Learn-SQL-Basics-for-Data-Science/844aaf928966f21e0d6a04a6cb76a2e4dba4c7eb/C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/week_1/sol.odt -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/week_2/quiz.txt: -------------------------------------------------------------------------------- 1 | 1. 2 | Question 1 3 | Which step should happen first in data analysis? 4 | 5 | v Collecting Data 6 | 7 | Question 2 8 | TROUBLESHOOT THIS ERROR by selecting appropriate actions to remedy this specific query? 9 | v Run DESCRIBE TABLE example_table to see if the existing example_table is structured appropriately 10 | 11 | Question 3 12 | 13 | table_x is dependent on table_y and dates_rollup 14 | table_x is dependent on table_y 15 | 16 | 4. 17 | Question 4 18 | Based on what you know about the orders table for this class, which of the following columns have a suitable datatype? 19 | 20 | Invoice_id 21 | user_id 22 | 23 | 5.Question 5 24 | For this class, we are using Mode on a dataset specifically created for this course. 25 | Which of these circumstances could be different in a real world situation? (Select all that apply.) 26 | 27 | The specific dialect of SQL 28 | How frequently the data is updated 29 | 30 | 31 | 6. Based on what you know about the items table for this class, 32 | which of the following columns have a suitable datatype? (Select all that apply.) 33 | category 34 | name 35 | 36 | 7.Which of the following table methods allows you to specify data types? 37 | 38 | MAKE NEW TABLE 39 | example_table 40 | AS … 41 | 42 | 8. When creating a user info table we used a variable in place of which column? 43 | 44 | the user 45 | 46 | 9. Suppose in a table, you find a column called email which contains the value user@domain.com. What is the correct data type category for this column? 47 | 48 | string 49 | 50 | 10. In this module, we created a table specifically of item view events. What level of the hierarchy of data does this belong on? 51 | Explore and Transform 52 | 53 | 11. Suppose in a table you find a column called event_id, which contains the value z87df6ab4waoa756b3. What is the correct data type category for this column? 54 | String -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/week_3/Create-a-Rollup-Table.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/urbanclimatefr/Coursera-Learn-SQL-Basics-for-Data-Science/844aaf928966f21e0d6a04a6cb76a2e4dba4c7eb/C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/week_3/Create-a-Rollup-Table.pdf -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/week_3/Product-Analysis.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/urbanclimatefr/Coursera-Learn-SQL-Basics-for-Data-Science/844aaf928966f21e0d6a04a6cb76a2e4dba4c7eb/C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/week_3/Product-Analysis.pdf -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/week_3/Promo-Email.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/urbanclimatefr/Coursera-Learn-SQL-Basics-for-Data-Science/844aaf928966f21e0d6a04a6cb76a2e4dba4c7eb/C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/week_3/Promo-Email.pdf -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/week_3/quiz_3.txt: -------------------------------------------------------------------------------- 1 | 1. 2 | Question 1 3 | Which of the following attributes distinguish a work-in-progress from a “polished” final query? (Select all that apply.) 4 | Every column has a descriptive name 5 | The query is formatted consistently, or according to a style guide 6 | 7 | 2.Question 2 8 | In which of the following sections did we perform analysis to directly guide decision making? 9 | X Creating a view items table 10 | 11 | 3. 3. 12 | Question 3 13 | Which of the following are uses of a dates rollup table? 14 | V Efficiently computing aggregates over a rolling time period 15 | V For keeping track of your meeting schedule 16 | 4. 17 | Question 4 18 | We’ve decided to only use the items and users tables to answer the following questions: 19 | 20 | How many items have been purchased? 21 | How many items do we have? 22 | Which join type and order will allow us to correctly compute the columns Item_count, items_ever_purchased_count? 23 | 24 | SELECT * 25 | 26 | FROM 27 | 28 | dsv1069.items 29 | 30 | LEFT OUTER JOIN 31 | 32 | dsv1069.orders 33 | 34 | ON 35 | 36 | items.id = orders.item 37 | 38 | X 39 | SELECT * 40 | 41 | FROM 42 | 43 | dsv1069.orders 44 | 45 | LEFT JOIN 46 | 47 | dsv1069.items 48 | 49 | ON 50 | 51 | items.id = orders.item 52 | 53 | 5. For this statement, fill in the __ with the appropriate inequality (<, <=, =, >=, >): 54 | 55 | For days in any given week 56 | 57 | Daily unique visitors _ Weekly Unique visitors 58 | > 59 | 60 | 6. Select the best definition of a windowing function? 61 | It is a function that computes a value on a certain partition, 62 | or window, of the data that is specified in the PARTITION BY statement. 63 | 64 | 7. Folks at the company wonder if our product catalog is too big. 65 | What are some related questions that you could directly answer with data? (Select all that apply.) 66 | v How many items do we have? 67 | v How many items have been purchased? 68 | 69 | How many users have purchased an item? 70 | 8. 71 | Question 8 72 | Which of the following tasks can be accomplished with a windowing function? (Select all that apply.) 73 | Find the most recently viewed item 74 | Find the most expensive item per order 75 | 76 | 9. 77 | Question 9 78 | Let’s suppose we want to write a query to answer both of these questions: 79 | 80 | How many users have made a purchase? 81 | How many users do we have? 82 | Please choose the best set of columns for a final query that would answer these questions: 83 | 84 | user_count 85 | users_with_purchases 86 | 87 | 10. 88 | Question 10 89 | According to the methodology suggested in this module, which step comes first? 90 | 91 | Identify the question you are trying to answer -------------------------------------------------------------------------------- /C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/week_4/quiz.odt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/urbanclimatefr/Coursera-Learn-SQL-Basics-for-Data-Science/844aaf928966f21e0d6a04a6cb76a2e4dba4c7eb/C2-Data_Wrangling_Analysis_and_AB_Testing_with_SQL/week_4/quiz.odt -------------------------------------------------------------------------------- /C3-Distributed-Computing-with-Spark-SQL-main/assignments/module1-assignment1.md: -------------------------------------------------------------------------------- 1 | 1. What is the first value for "Incident Number"? 2 | 3 | - 16000003 4 | 5 | 2. What is the first value for "Incident Number" on April 4th, 2016? 6 | 7 | - 16037478 8 | 9 | 3. Is the first fire call in this table on Brooke or Conor's birthday? Conor's birthday is 4/4 and Brooke's is 9/27 (in MM/DD format). 10 | 11 | - Conor 12 | 13 | 4. W​hat is the "Station Area" for the first fire call in this table? Note that this table is a subset of the dataset. 14 | 15 | - 29 16 | 17 | 5. H​ow many incidents were on Conor's birthday in 2016? 18 | 19 | - 80 20 | 21 | 6. H​ow many fire calls had an "Ignition Cause" of "4 act of nature"? 22 | 23 | - 5 24 | 25 | 7. W​hat is the most common "Ignition Cause"? 26 | 27 | - 2 unintentional 28 | 29 | 8. W​hat is the total incidents from the two joined tables? 30 | 31 | - 847094402 -------------------------------------------------------------------------------- /C3-Distributed-Computing-with-Spark-SQL-main/assignments/module2-assignment2.md: -------------------------------------------------------------------------------- 1 | 1. H​ow many fire calls are in our table? 2 | 3 | - 240613 4 | 5 | 2. W​hich "Unit Type" is the most common? 6 | 7 | - ENGINE 8 | 9 | 3. W​hat type of transformation, wide or narrow, did the 'GROUP BY' and 'ORDER BY' queries result in? 10 | 11 | - Wide 12 | 13 | 4. H​ow many tasks were in the last stage of the last job? 14 | 15 | - 2 -------------------------------------------------------------------------------- /C3-Distributed-Computing-with-Spark-SQL-main/assignments/module3-assignment3.md: -------------------------------------------------------------------------------- 1 | 1. W​hat type of table is "newTable"? 2 | 3 | - EXTERNAL 4 | 5 | 2. H​ow many rows are in "newTable"? 6 | 7 | - 191039 8 | 9 | 3. W​hat is the "Battalion" of the first entry in the sorted table? 10 | 11 | - B01 12 | 13 | 4. W​as this query faster or slower on the table with increased partitions? 14 | 15 | - Slower 16 | 17 | 5. D​oes the data stored within the table still exist at the original location ('dbfs:/tmp/newTableLoc') after you dropped the table? 18 | 19 | - Yes -------------------------------------------------------------------------------- /C3-Distributed-Computing-with-Spark-SQL-main/assignments/module4-assignment4.md: -------------------------------------------------------------------------------- 1 | 1. H​ow many calls of 'Call_Type_Group' "Fire"? 2 | 3 | - 4196 4 | 5 | 2. H​ow many rows are in 'fireCallsGroupCleaned'? 6 | 7 | - 134198 8 | 9 | 3. W​hat is the accuracy of our model on test data as a percentage? Round to the nearest percent. (e.g. an accuracy of ".125" should be reported as "13") 10 | 11 | - 82 12 | 13 | 4. W​hat two values are in the 'prediction' column? 14 | 15 | - 0 16 | - 1 -------------------------------------------------------------------------------- /C3-Distributed-Computing-with-Spark-SQL-main/quizes/module1-quiz.md: -------------------------------------------------------------------------------- 1 | 1. Which of the following are true when it comes to the business value of big data? (Select all that apply.) 2 | 3 | - Businesses are increasingly making data-driven decisions 4 | 5 | - The size of the data businesses collect is growing 6 | 7 | 2. Spark uses...(Select all that apply.) 8 | 9 | - A distributed cluster of networked computers made of a driver node and many executor nodes 10 | 11 | - A driver node to distribute work across a number of executor nodes 12 | 13 | 3. How does Spark execute code backed by DataFrames? (Select all that apply.) 14 | 15 | - It separates the "logical plan" of what you want to accomplish from the "physical plan" of how to do it so it can optimize the query 16 | 17 | - It optimizes your query by figuring out the best "how" to execute what you want 18 | 19 | 4. What are the properties of Spark DataFrames? (Select all that apply.) 20 | 21 | - Resilient: Fault-tolerant 22 | 23 | - Distributed: Computed across multiple nodes 24 | 25 | - Dataset: Collection of partitioned data 26 | 27 | 5. What is the difference between Spark and database technologies? (Select all that apply.) 28 | 29 | - Spark is a highly optimized compute engine and is not a database 30 | 31 | - Spark is a computation engine and is not for data storage 32 | 33 | 6. What is Amdahl's law of scalability? (Select all that apply.) 34 | 35 | - Amdahl's law states that the speedup of a task is a function of how much of that task can be parallelized 36 | 37 | - A formula that gives the theoretical speedup as a function of the percentage of a computation that can be parallelized 38 | 39 | 7. Spark offers a unified approach to analytics. What does this include? (Select all that apply.) 40 | 41 | - Spark code can be written in the following languages: SQL, Scala, Java, Python, and R 42 | 43 | - Spark is able to connect to data where it lives in any number of sources, unifying the components of a data application 44 | 45 | - Spark allows analysts, data scientist, and data engineers to all use the same core technology 46 | 47 | - Spark unities applications such as SQL queries, streaming, and machine learning 48 | 49 | 8. What is a Databricks notebook? 50 | 51 | - A collaborative, interactive workspace that allows you to execute Spark queries at scale 52 | 53 | 9. How can you get data into Databricks? (Select all that apply.) 54 | 55 | - By uploading it through the user interface 56 | 57 | - By "mounting" data backed by cloud storage 58 | 59 | - By registering the data as a table 60 | 61 | 10. What are the qualities of big data? (Select all that apply.) 62 | 63 | - Volume 64 | 65 | - Velocity 66 | 67 | - Veracity 68 | 69 | - Variety -------------------------------------------------------------------------------- /C3-Distributed-Computing-with-Spark-SQL-main/quizes/module2-quiz.md: -------------------------------------------------------------------------------- 1 | 1. What are the different units of parallelism? (Select all that apply.) 2 | 3 | - Partition 4 | 5 | - Core 6 | 7 | - Executor 8 | 9 | - Task 10 | 11 | 2. What is a partition? 12 | 13 | - A portion of a large distributed set of data 14 | 15 | 3. What is the difference between in-memory computing and other technologies? (Select all that apply.) 16 | 17 | - In-memory operates from RAM while other technologies operate from disk 18 | 19 | - Computation not done in-memory (such as Hadoop) reads and writes from disk in between each step 20 | 21 | - In-memory operations were not realistic in older technologies when memory was more expensive 22 | 23 | 4. Why is caching important? 24 | 25 | - It stores data on the cluster to improve query performance 26 | 27 | 5. Which of the following is a wide transformation? (Select all that apply.) 28 | 29 | - ORDER BY 30 | 31 | - GROUP BY 32 | 33 | 6. Broadcast joins... 34 | 35 | - Transfer the smaller of two tables to the larger, minimizing data transfer 36 | 37 | 7. When is it appropriate to use a shuffle join? 38 | 39 | - When both tables are moderately sized or large 40 | 41 | 8. Which of the following are bottlenecks you can detect with the Spark UI? (Select all that apply.) 42 | 43 | - Shuffle reads 44 | 45 | - Shuffle writes 46 | 47 | - Data Skew 48 | 49 | 9. What is a stage boundary? 50 | 51 | - When all of the slots or available units of processing have to sync with one another 52 | 53 | 10. What happens when Spark code is executed in local mode? 54 | 55 | - The executor and driver are on the same machine 56 | -------------------------------------------------------------------------------- /C3-Distributed-Computing-with-Spark-SQL-main/quizes/module3-quiz.md: -------------------------------------------------------------------------------- 1 | 1. Decoupling storage and compute means storing data in one location and processing it using a separate resource. What are the benefits of this design principle? (Select all that apply.) 2 | 3 | - It allows for elastic resources so larger storage or compute resources are used only when needed 4 | - It makes updates to new software versions easier 5 | - Resources are isolated and therefore more manageable and debuggable 6 | 7 | 2. You want to run a report entailing summary statistics on a large dataset sitting in a database. What is the main resource limitation of this task? 8 | 9 | - IO: the transfer of data is more demanding than the computation 10 | 11 | 3. Processing virtual shopping cart orders in real time is an example of... 12 | 13 | - OLTP 14 | 15 | 4. When are BLOB stores an appropriate place to store data? (Select all that apply.) 16 | 17 | - For storing large files 18 | - For cheap storage 19 | - For a "data lake" of largely unstructured data 20 | 21 | 5. JDBC is the standard protocol for interacting with databases in the Java environment. How do parallel connections work between Spark and a database using JDBC? 22 | 23 | - Specify a column, number of partitions, and the column's minimum and maximum values. Spark then divides that range of values between parallel connections. 24 | 25 | 6. What are some of the advantages of the file format Parquet over CSV? (Select all that apply.) 26 | 27 | - Parallelism 28 | - Compression 29 | - Columnar 30 | 31 | 7. SQL is normally used to query tabular (or "structured") data. Semi-structured data like JSON is common in big data environments. Why? (Select all that apply.) 32 | 33 | - It allows for missing data 34 | - It does not need a formal structure 35 | - It allows for data change over time 36 | - It allows for complex data types 37 | 38 | 8. Data writes in Spark can happen in serial or in parallel. What controls this parallelism? 39 | 40 | - The number of data partitions in a DataFrame 41 | 42 | 9. Fill in the blanks with the appropriate response below: 43 | 44 | A _________ table manages _________ and a DROP TABLE command will result in data loss. 45 | 46 | - managed, both the data and metadata such as the schema and data location -------------------------------------------------------------------------------- /C3-Distributed-Computing-with-Spark-SQL-main/quizes/module4-quiz.md: -------------------------------------------------------------------------------- 1 | 1. Machine learning is suited to solve which of the following tasks? (Select all that apply.) 2 | 3 | - Image Recognition 4 | - Fraud Detection 5 | - Natural Language Processing 6 | - Financial Forecasting 7 | - Churn Analysis 8 | - A/B testing 9 | 10 | 2. Is a model that is 99\% accurate at predicting breast cancer a good model? 11 | 12 | - Likely no because there are not many cases of cancer in a general population 13 | 14 | 3. What is an appropriate baseline model to compare a machine learning solution to? 15 | 16 | - The average of the dataset 17 | 18 | 4. What is Machine Learning? (Select all that apply.) 19 | 20 | - A function that maps features to an output 21 | - Learning patterns in your data without being explicitly programmed 22 | 23 | 5. (Fill in the blanks with the appropriate answer below.) 24 | 25 | Predicting whether a website user is fraudulent or not is an example of _________ machine learning. It is a __________ task 26 | 27 | - supervised, classification 28 | 29 | 6. (Fill in the blanks with the appropriate answer below.) 30 | 31 | Grouping similar users together based on past activity is an example of _________ machine learning. It is a _________ task. 32 | 33 | - unsupervised, clustering 34 | 35 | 7. Predicting the next quarter of a company's earnings is an example of... 36 | 37 | - Regression 38 | 39 | 8. Why do we want to perform a train/test split before we train a machine learning model? (Select all that apply.) 40 | 41 | - To evaluate how our model performs on unseen data 42 | - To keep the model from "overfitting" where it memorizes the data it has seen 43 | 44 | 9. What is a linear regression model learning about your data? 45 | 46 | - The formula for the line of best fit 47 | 48 | 10. How do you define a custom function not already part of core Spark? 49 | 50 | - With a User-Defined Function -------------------------------------------------------------------------------- /C4-SQL-for-Data-Science-Capstone-Project/SportsStats/ERD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/urbanclimatefr/Coursera-Learn-SQL-Basics-for-Data-Science/844aaf928966f21e0d6a04a6cb76a2e4dba4c7eb/C4-SQL-for-Data-Science-Capstone-Project/SportsStats/ERD.png -------------------------------------------------------------------------------- /C4-SQL-for-Data-Science-Capstone-Project/SportsStats/athlete_events.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/urbanclimatefr/Coursera-Learn-SQL-Basics-for-Data-Science/844aaf928966f21e0d6a04a6cb76a2e4dba4c7eb/C4-SQL-for-Data-Science-Capstone-Project/SportsStats/athlete_events.zip -------------------------------------------------------------------------------- /C4-SQL-for-Data-Science-Capstone-Project/SportsStats/noc_regions.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/urbanclimatefr/Coursera-Learn-SQL-Basics-for-Data-Science/844aaf928966f21e0d6a04a6cb76a2e4dba4c7eb/C4-SQL-for-Data-Science-Capstone-Project/SportsStats/noc_regions.zip -------------------------------------------------------------------------------- /C4-SQL-for-Data-Science-Capstone-Project/SportsStats/presentation.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/urbanclimatefr/Coursera-Learn-SQL-Basics-for-Data-Science/844aaf928966f21e0d6a04a6cb76a2e4dba4c7eb/C4-SQL-for-Data-Science-Capstone-Project/SportsStats/presentation.pptx -------------------------------------------------------------------------------- /C4-SQL-for-Data-Science-Capstone-Project/SportsStats/week1_data_analysis.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Preparing for Your Proposal \n", 8 | " \n" 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "## Which client/dataset did you select and why? \n", 16 | "\n" 17 | ] 18 | }, 19 | { 20 | "cell_type": "markdown", 21 | "metadata": {}, 22 | "source": [ 23 | "Client 3: SportsStats (Olympics Dataset - 120 years of data) \n", 24 | "SportsStats is a sports analysis firm partnering with local news and elite personal trainers to provide \t“interesting” insights to help their partners. Insights could be patterns/trends highlighting certain \tgroups/events/countries, etc. for the purpose of developing a news story or discovering key health \tinsights. \n", 25 | "\n", 26 | "I selected SportsStats client, because of two reasons: \n", 27 | "\n", 28 | "1) the size of the SportsStats data is smaller than the others. This makes data wrangling and analysis \teasier; 2) I am interested in sports and working with sports analytics \n", 29 | "\n" 30 | ] 31 | }, 32 | { 33 | "cell_type": "markdown", 34 | "metadata": {}, 35 | "source": [ 36 | "## Describe the steps you took to import and clean the data. \n", 37 | " " 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": {}, 43 | "source": [ 44 | "To import the data, I used pandas to read the CSV files. I used in-built pandas to_sql() to store the \tdata in MySQL dataset. I did not clean the data because the dataset has NaN values. " 45 | ] 46 | }, 47 | { 48 | "cell_type": "markdown", 49 | "metadata": {}, 50 | "source": [ 51 | "## Importing the data" 52 | ] 53 | }, 54 | { 55 | "cell_type": "code", 56 | "execution_count": 1, 57 | "metadata": {}, 58 | "outputs": [], 59 | "source": [ 60 | "import pandas as pd\n", 61 | "from pandasql import sqldf\n", 62 | "pysqldf = lambda q: sqldf(q, globals())\n", 63 | "\n", 64 | "athlete_events = pd.read_csv(\"athlete_events.csv\")\n", 65 | "noc_regions = pd.read_csv(\"noc_regions.csv\")\n" 66 | ] 67 | }, 68 | { 69 | "cell_type": "markdown", 70 | "metadata": {}, 71 | "source": [ 72 | "Aftering importing the data, the next step is to dividie the athelte_events table into winter and summer tables. \"Team\", \"Games\", \"Season\", and \"City\" columns are not selected, since they provide us with either repetiitive or unnecessary information:" 73 | ] 74 | }, 75 | { 76 | "cell_type": "code", 77 | "execution_count": 2, 78 | "metadata": {}, 79 | "outputs": [], 80 | "source": [ 81 | "summer_events = pysqldf('''SELECT\n", 82 | " ID,\n", 83 | " Name,\n", 84 | " Sex,\n", 85 | " Age,\n", 86 | " Height,\n", 87 | " Weight,\n", 88 | " NOC,\n", 89 | " Year,\n", 90 | " Sport,\n", 91 | " Event,\n", 92 | " Medal\n", 93 | " FROM\n", 94 | " athlete_events\n", 95 | " WHERE\n", 96 | " Season = \"Summer\"''')\n", 97 | "\n", 98 | "winter_events = pysqldf('''SELECT\n", 99 | " ID,\n", 100 | " Name,\n", 101 | " Sex,\n", 102 | " Age,\n", 103 | " Height,\n", 104 | " Weight,\n", 105 | " NOC,\n", 106 | " Year,\n", 107 | " Sport,\n", 108 | " Event,\n", 109 | " Medal\n", 110 | " FROM\n", 111 | " athlete_events\n", 112 | " WHERE\n", 113 | " Season = \"Winter\"''')" 114 | ] 115 | }, 116 | { 117 | "cell_type": "markdown", 118 | "metadata": {}, 119 | "source": [ 120 | "## Initial exploration of the data" 121 | ] 122 | }, 123 | { 124 | "cell_type": "markdown", 125 | "metadata": {}, 126 | "source": [ 127 | "Out of 271116 data points, 9474 lack age value, 60171 lack height value, 62875 lack weight value. Sex values are complete. Games data and its attributes (year, city, etc.) are complete.Since team names can be changed, using NOC instead would prove more consistent." 128 | ] 129 | }, 130 | { 131 | "cell_type": "code", 132 | "execution_count": 3, 133 | "metadata": {}, 134 | "outputs": [ 135 | { 136 | "data": { 137 | "image/png": "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Xhs/wUmKssqjpGBAOuX33Xff2aZNm+ybb76xr7/+2jZu3GhfffWVy58vv/zSvvjiC1u3bp19/vnntmbNGlu9erW7b/LTTz+1//3vf7Zy5UpbsWKFffLJJ7Z8+XJbtmyZ+8H98MMPbenSpbZ48WL74IMPbNGiRbZw4UJbsGCBvf/++/bee++5Mps3b567//K///2vzZkzx2bPnm3/+c9/7K233rI333zT3njjDTd6s0Zxfu2111wXzVdffdWmT59u//73v23atGk2depUmzJlik2ePNkmTZpkEydOtAkTJthLL71k48ePtxdffNHGjh1r//rXv+yFF16wf/7zn/b888/bmDFj3Enec889Z6NGjbJnnnnGRo4caaqfn376aRsxYoQ9+eST9ve//90dM8OHD7ehQ4e6AaQGDx5sgwYNsscff9wee+wxGzhwoA0YMMAeffRR69+/v/3tb3+zvn37uumnHn74YevTp4/17t3bHnroIevZs6c9+OCD9sADD9j9999v9957r91zzz3Wo0cP6969uzsh1XF69913uytRyidOGPMn9YRSVwhVNiojNRBUXio3laHK8r777nPlqvJVOau8Ve69evVyx4COBR0XOj769evnjhUdMzp2dAzpWNIx9X//93/u+NJxpmNOx96wYcPccajjUceljk8dp0899ZQ7ZnXs6jjW8fzss8+6Y1vHuI51HfMaAV3Hv74L+k7ouzFu3Dj3PdH3Rd8bfX/0PdL3Sd8rfb/0PVNdqe+cvnv6Duq7OHPmzC0jrOu7qu+svrtvv/22+x7r+6zv9jvvvOO+5/q+63jW91/1wPz5812doPpB9YTqiyVLlri6Q3WI8l51yscff+zqGNU1qnNU96iuVz2k+kj1kuqntWvXuvpK9ZbqL9Vjqs82bNjg6jbVcarvvv32W1f3laesOrS0denUu7mg8oqfXOuYif8uRr+TysP4b2H8tzH+f/T8+Ouj99d3QQ+JvyYEJZVHSWn6Tpe0zUrTukxJrU+oz7MrX/ldVj1Q2rqyXpMPOva1Tfobfa+j77nqk9KCf3qO1ku83ok/T6/TObvSoudFrwlFNsuDQAASIbRKKRKvZFShqJLRyWdlAgGhVTxlUXlk8rHtttvadtttZ9tvv73tuOOOttNOO9mPfvQj23nnnW2XXXax3XbbzXbffXfbY489bM8997S99trL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AIBseffdd+1Xv/qV/eEPf/AphUuzmWn2BACVk5NAQCpdSVejWoPrtW/f3nWVbtq0qfu/T58+7p55zTe/ePFiW79+vX9V5ug99d76DH2WPlOfrW3Qtuh/bZu2MV8j/H/77bduzIHTTjvNzjjjDBs4cKBfU/h69uxphx9+uM2aNcunFA7tk8oTAAAgG7755hs3HlGdOnVs1apVPrUwbbfddu6cGUDF5SUQUJLly5e7hvnIkSOtd+/erhu+rsTXq1fPVWSq0Nq0aePSu3bt6hqLffv2dQ1kzdE/ZMgQ99D/StM6PUfP1Wv02qhS1HvqvXV/v4IA+kx9trYhROrq1ahRI3cf1O23357WgIRJp7lx99lnH5s0aZJPKQwayOeEE07wSwAAANmhc8Zjjz3WXnvtNZ9SeHbdddeiHV8LqKpgAgFlWbt2rS1dutTmzJlj06dPt5deesnGjBnj7tt/4oknbOjQoTZ48GD30P9K0zo9R8/Va/RavYfeK6m0DzfffLPtvPPOduWVV9q0adP8msKkMtx+++1t9OjRPiX5dOvHkUce6ZcAAACyR+fGO+ywg5u1qBDtu+++9umnn/olABWRiEAAtqZgxoMPPmjHHHOMXXDBBfb3v//dryk8GiNh9913dwGeQvDJJ5/YT37yE78EAACQXRqfSLdcqpdsoTnooINs2bJlfglARRAISDiVX40aNdxV5nvuuacg7wV79dVX7eCDD7ZHHnnEpyQXI9wCAIBc++ijj6x69eru1thCovPfhQsX+iUAFUEgoEBojAPNxa+u9DfeeKO9+eabfk1h0L31xx13nHXv3t2nJNPXX39tO+64o18CAADIndatW7vZiz744AOfkmzHH398UU65DWQCgYACowEP7777bjvkkEOsbt26BXV//YcffmhnnXWWdejQwack0zbbbOP/AwAAyK17773X9bScMGGCT0kuza5VaBe/gFwhEFDANEDMueeeayeeeKI9/PDD9tVXX/k1yaXxEXQrhHo9JBWBAAAAkE+aMWuXXXZx02Un2TnnnOMGBQdQcQQCioCm4GvWrJm7N719+/b23nvv+TXJ1bRpU2vRooVfShYCAQAAIN90JV0Xi5Lc07JatWoFN9U0kCsEAorIggULXGW/995726WXXuqmVkyyq6++2urVq2cbNmzwKclAIAAAAIRAgxg3bNjQXWBJ4nz8derUsX/9619+CUBFEAgoQhqwrm/fvnbKKae4e+4ff/xxvyZ52rZt6wa9WblypU8JH4EAAAAQkj/96U926qmn2pw5c3xKMjRq1MieffZZvwSgIggEFLl//OMfVr9+fTcP65133umml0kabbeCGurxkAQEAgAAQGj69etne+yxR6IGmtatryNGjPBLACqCQACc//znP/b73//eTW2nOWaTNvDKgw8+aEcccUQiRo4lEAAAAEL04osv2gEHHGA9e/b0KWHTOasGxwZQcQQCsJXVq1fbfffdZ0cffbRVr17dnnrqKb8mfI899pjtu+++9vLLL/uU/LjrrrtcY7+yD70eAAAgH+bPn29nn3223XTTTT4lXJpFqn///n4JQEUQCECpFARQMEBBAQUHFCQI3dNPP2077LCDjRkzxqeER419AACAUH333Xd2xRVXWK1atWzFihU+NTwaK6pXr15+CUBFEAhAuXSbgLpe6bYB3T6g2whCNnbsWNttt91s+PDhPiUsBAIAAEASaBwmXRAK9ZbRTp062T333OOXAFQEgQCkTQMJ6gdBAwtqgMHnn3/erwmPfrC0nZodITQEAgAAQFIMHTrUtt122yAvsOh2Sm6pBCqHQAAqRVMOaupBjdavxramJAzNf//7Xzv22GOtR48ePiX/WrRo4QIB+gsAAJAEr7zyih111FH217/+1aeEQb0B1CsAQMURCECVvPTSS3bppZfa3nvvbR06dAhuCr+lS5famWeeGcSPhBr/8UAAwQAAAJAUy5cvtxo1atiVV17pU/JP4wNonAAAFUcgABnx3nvvWfv27W3PPfd0c7pOnDjRr8m/zz//3C666CJr06aNT8m9eMM/ujWAYAAAAEgajdR/7rnnBnHxRzMGaHsAVByBAGTUV199ZQ8//LCdeOKJ7kcipLldmzRp4kbAzbXUBn98jACCAQAAIGkeeOABO/DAA23cuHE+JT90nqkBrQFUHIEAZM3o0aOtbt26dsghh9jdd9/tupTlm34sNNBhrsY0KKmhnzpYIMEAAACQNM8++6ztvvvu9re//c2n5N6IESNcT1QAFUcgAFn35ptvum5b22+/vV177bU2Y8YMvyY/brnlFjv//PPtf//7n0/JjtIa+KmBACEYAAAAkkZTSmvg6FtvvdWn5JaCEY0aNfJLQMWsXbvWlixZYnPmzHEzjmnsszFj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7aDnpk7toPfUe+v+fn2WPjPkqR0K2WeffeZ+XPbcc0+75pprbPbs2X5N9vzzn/+0HXfc0V2dzzVNI6KAEwAAQOhWrFjhBsRWD9mQz5NPOumknJxDAoUkmEBAWSo7tYOeUwhTOxQi/bDo1otddtnFbrjhhpxFcUeMGGE/+tGP7IUXXvApuaUeKI0bN/ZLAAAAYdJg2Bqr6Y477vAp4Tr99NOz3psUKDSJCASgcGggF916sf3229sf//jHnA4e+dhjj9l+++2X1xFudX9do0aN/BIAAEB4NF7Tvvvu6y5gJME555zjLvwBSB+BAOTEokWL7Oabb7btttvOjYyu3hm5pMEeDz/8cHvjjTd8Sn6ol4q62AEAAIRGg2I3a9bMqlevnqjB984///xgpjIEkoJAALLqvffec+MzqDu+xmrIx/1lGifiF7/4hduWfHv++efdfXYAAAAhmTZtmht0Tz03k0ZTGup2YADpIxCArNCYDNdee63tscce7t6yTz/91K/JLQUfzjrrrGCmZtNAhRqsEgAAIBSPPPKI7bzzzjZ8+HCfkix169bN2/hPQFIRCEBGvfnmm/a73/3O3VfWpUuXvA7O+Pvf/95++9vfBjVApH6k9GMFAACQb99++627cHP22We7izhJpem/R48e7ZcApINAADJC0y/qnrKf/OQnds8999hXX33l1+THVVdd5X4UvvvuO58SBs2/W7t2bb8EAACQHxo36Ze//KXdeOONPiW5Lr30UjdjGID0EQhAleh+Ms2Lf+ihh1rPnj1dZDnftD1XXHGFXwrLiy++aDVr1vRLAAAAuff444+7AZwfffRRn5JsOu/T9OEA0kcgAJUyadIkN/r9UUcdZQ8//LBPza8vv/zSatWqZTfccINPCc/48eOtRo0afgkAACC3NH3zySefbK+99ppPSb5WrVrZ4MGD/RKAdBAIQIXoira6tmtU2ZCiyCtWrLBf//rXduutt/qUME2YMMGNWwAAAJBL8+bNs/POO8+N5bRx40afWhiuv/56GzBggF8CkA4CAUjLP/7xD9eAPemkk1x3spBonttTTjnF/vrXv/qUcE2cONHNzQsAAJArI0aMsN13390eeughn1JY/vCHP7iZDwCkj0AAyjRq1CgXPT799NNt2LBhPjUc//nPf+xnP/uZPfjggz4lbC+//LJdeOGFfgkAACC7NJXy0Ucf7W7rLFTt2rUr2CAHkC0EAlCip556yk0lo4f+D9G///1vO/DAAxM10M3kyZPtggsu8EsAAADZsXTpUjd20iWXXGKrV6/2qYVJwY57773XLwFIB4EAbGX48OHu6r96Aag3QKjGjRtnu+66a+JGiJ06darLWwAAgGwZM2aMu1jSrVs3n1LY7rjjDuvSpYtfApAOAgFwdN+/7v/XOAAaDyBkClBoypvRo0f7lOTQdIsa1BAAACAb7r77bjv44IPtn//8p08pfAoCKBgAIH0EAoqcutVrBgDNBKAZAUI3dOhQ23PPPd3o+0mk2xnOPfdcvwQAAJAZq1atssaNG1vdunXto48+8qnFQbcF6PYAAOkjEFCkNPf/UUcdZfXr13cj2SdBv379XIR7xowZPiV5pk+f7sZdAAAAyBRdIDnyyCPtz3/+s08pLj179nQDBgJIH4GAIvLtt9+6ivLQQw+1pk2bum7qSXHffffZMcccY//97399SjIpiHHWWWf5JQAAgKp54IEHbK+99rJiPqfX1IGaQhBA+ggEFIENGza4LlM/+clPrFmzZom7oq57vn75y1/a4sWLfUpyzZw5084880y/BAAAUDnr16+3K664ws1G9P777/vU4jRgwAC7/vrr/RKAdBAIKGBr1651g6fsu+++9rvf/c7efPNNvyY51M3r/PPPd/e9FYLXX3/dzjjjDL8EAABQcbrV8Be/+IW1bdvWpxS3QYMGWatWrfwSgHQQCChAn376qbuKvscee9i1115rc+bM8WuS5brrrnMD3qhHQ6F44403XO8GAACAyvjb3/5mO+64ow0ZMsSnQNNJq3cEgPQRCCggy5cvdyOm/uhHP7Ibb7zR3n33Xb8meXQLw2WXXeaXCod6ZZx66ql+CQAAIH2tW7d2txi+/fbbPgWi9syll17qlwCkg0BAAVi6dKn96U9/cnPr33zzzbZo0SK/Jnm++eYbu/jii+2aa67xKYVFP9ynnHKKXwIAACifzh8UAFAgAD/03HPPWcOGDf0SgHQQCEiwhQsX2h//+EfbfvvtrX379vbhhx/6Ncm0evVqu/DCC10wo1D95z//sZNOOskvAQAAlE23AOhWAN0SgJK98MIL7nZSAOkjEJBA8+bNsxtuuMF22WUX69y5s61YscKvSS4FMTSIXqHPf6vxGk488US/BAAAUDoNBqhBATU4IEr30ksv2UUXXeSXAKSDQECCzJ4923WZ33PPPe3OO++0zz77zK9JNgU2jjvuOOvRo4dPKVzvvPOOnXDCCX4JAADghzQdoHpJagA8TROIsk2ePNnNMgUgfQQCEmDWrFl25ZVX2v77729du3a1L774wq9JPs2r/9Of/tQefvhhn1LY5s6da8cff7xfAgAA2JrOzffaay974IEHfArKox4T55xzjl8CkA4CAQF79dVX7fLLL7eDDjrI7rvvPtu4caNfUxgmTZpke++9t5v7tVhoJodjjz3WLwEAAHxPt0geeeSRNmHCBJ+CdOii2emnn+6XAKQjEYGAtWvXupHxdX+1In66D2jMmDEuYqp5Q4cOHWqDBw92D/2vNK3Tc/RcvUav1XvovUI3depUa9KkiR122GH20EMP2XfffefXFI7nn3/edthhB1dOxeS9996zY445xi8BAACYffTRR26wu8aNG9uqVat8KtLFYMxAxQUTCNAc+DNmzLCRI0da7969rVOnTtaqVSurV6+e1alTx5o3b25t2rRx8+Sre3zPnj2tb9++NnDgQHdFWSOq6qH/laZ1eo6eq9fotXoPvZfeU++tdH2WPlOfrW3IJ0V/NXXe0Ucf7ba/UD355JO2884727/+9S+fUjzmz5/vyhcAAED++c9/2sEHH2x33323T0FFReNNAUhfXgIBK1eudIN6DBgwwE17p3k/mzZt6v7v06ePjRo1yjXMFy9enJUBUvSeem99hj5Ln6nP1jZoW/S/tk3bqG3NtrFjx1qtWrXcveP63EKmII3GOlCvh2K0YMECO+qoo/wSAAAoZt26dbMDDzzQ9WJF5WlKbc6vgIrJSSBg3bp1rlHdq1cvdyW+fv36btq7YcOGucHi1qxZ45+Zf9oWbZO2TduobdU2a9u1D9qXTFGlX716dTv55JOL4j553eZwxBFH2FtvveVTis+iRYvcvX8AAKB4rV692i655BJ3IUi3rqJqNA21Bp8GkL6sBQJ0Jf25556zDh06WLVq1dxffZauiCaNtlnbHt8X7Vtlews888wz9pvf/MbNm6/xDIpBly5d3Pz56hpfzNQT5fDDD/dLAACg2GiwZN0mqFtUkRmffPKJ61kBIH0ZDQRs2rTJxo8f7+7vr127tnXv3t2mTJni0guF9kX7pH1TFFf7qn1OZx9HjBhhZ511lpve5Omnn/ap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\n", 138 | "text/plain": [ 139 | "" 140 | ] 141 | }, 142 | "execution_count": 3, 143 | "metadata": { 144 | "image/png": { 145 | "height": 400, 146 | "width": 800 147 | } 148 | }, 149 | "output_type": "execute_result" 150 | } 151 | ], 152 | "source": [ 153 | "from IPython.display import Image\n", 154 | "Image(filename = \"ERD.png\", width = 800, height = 400)" 155 | ] 156 | }, 157 | { 158 | "cell_type": "markdown", 159 | "metadata": {}, 160 | "source": [ 161 | "## Project Proposal" 162 | ] 163 | }, 164 | { 165 | "cell_type": "markdown", 166 | "metadata": {}, 167 | "source": [ 168 | "In this project, I would analyze the summer and winter Olympic games data. I try to figure out important changes in terms of diversity and performance. I also try to find correlation between several factors (such as representing the host country) and team performance. This would be beneficial to anyone interested in understanding the demographics of Olympic games." 169 | ] 170 | }, 171 | { 172 | "cell_type": "markdown", 173 | "metadata": {}, 174 | "source": [ 175 | "## Questions" 176 | ] 177 | }, 178 | { 179 | "cell_type": "markdown", 180 | "metadata": {}, 181 | "source": [ 182 | "Q1: Is there any correlation between the performance of a country in winter olympics and that in summer olympics?
\n", 183 | "Q2: Does country performance by year change more in Winter Olympics or Summer Olympics?
\n", 184 | "Q3: How has the male:female ratio evolved through time?" 185 | ] 186 | }, 187 | { 188 | "cell_type": "markdown", 189 | "metadata": {}, 190 | "source": [ 191 | "## Hypotheses" 192 | ] 193 | }, 194 | { 195 | "cell_type": "markdown", 196 | "metadata": {}, 197 | "source": [ 198 | "H1: Yes.
\n", 199 | "H2: Winter Olympics.
\n", 200 | "H3: Decreased." 201 | ] 202 | }, 203 | { 204 | "cell_type": "markdown", 205 | "metadata": {}, 206 | "source": [ 207 | "## Approach" 208 | ] 209 | }, 210 | { 211 | "cell_type": "markdown", 212 | "metadata": {}, 213 | "source": [ 214 | "A1: to calculate the Pearon correlation coefficient.
\n", 215 | "A2: to calculate the standard deviation in country performance through years. A Comparison between average std of Winter and that of Summer Olympics will help.
\n", 216 | "A3: to draw a simple histogram." 217 | ] 218 | }, 219 | { 220 | "cell_type": "code", 221 | "execution_count": null, 222 | "metadata": {}, 223 | "outputs": [], 224 | "source": [] 225 | } 226 | ], 227 | "metadata": { 228 | "kernelspec": { 229 | "display_name": "Python 3", 230 | "language": "python", 231 | "name": "python3" 232 | }, 233 | "language_info": { 234 | "codemirror_mode": { 235 | "name": "ipython", 236 | "version": 3 237 | }, 238 | "file_extension": ".py", 239 | "mimetype": "text/x-python", 240 | "name": "python", 241 | "nbconvert_exporter": "python", 242 | "pygments_lexer": "ipython3", 243 | "version": "3.7.7" 244 | } 245 | }, 246 | "nbformat": 4, 247 | "nbformat_minor": 4 248 | } 249 | -------------------------------------------------------------------------------- /C4-SQL-for-Data-Science-Capstone-Project/SportsStats/week1_data_analysis.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/urbanclimatefr/Coursera-Learn-SQL-Basics-for-Data-Science/844aaf928966f21e0d6a04a6cb76a2e4dba4c7eb/C4-SQL-for-Data-Science-Capstone-Project/SportsStats/week1_data_analysis.pdf -------------------------------------------------------------------------------- /C4-SQL-for-Data-Science-Capstone-Project/SportsStats/week3_beyond_descriptive_stats.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "id": "prostate-aluminum", 7 | "metadata": {}, 8 | "outputs": [ 9 | { 10 | "name": "stdout", 11 | "output_type": "stream", 12 | "text": [ 13 | "importing Jupyter notebook from week1_data_analysis.ipynb\n" 14 | ] 15 | } 16 | ], 17 | "source": [ 18 | "import pandas as pd\n", 19 | "import matplotlib.pyplot as plt\n", 20 | "from pandasql import sqldf\n", 21 | "pysqldf = lambda q: sqldf(q, globals())\n", 22 | "\n", 23 | "import import_ipynb\n", 24 | "from week1_data_analysis import summer_events, winter_events" 25 | ] 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "id": "sized-break", 30 | "metadata": {}, 31 | "source": [ 32 | "## Beyond Descriptive Stats" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 2, 38 | "id": "motivated-change", 39 | "metadata": {}, 40 | "outputs": [], 41 | "source": [ 42 | "#Summer Olympics:\n", 43 | "summer_medal_count = pysqldf('''\n", 44 | " SELECT\n", 45 | " Year,\n", 46 | " COUNT(*) AS total_count,\n", 47 | " SUM(CASE\n", 48 | " WHEN Medal IS NOT NULL THEN 1 ELSE 0\n", 49 | " END) AS medal_count,\n", 50 | " SUM(CASE\n", 51 | " WHEN Medal = \"Gold\" THEN 1 ELSE 0\n", 52 | " END) AS gold_count,\n", 53 | " SUM(CASE\n", 54 | " WHEN Medal = \"Silver\" THEN 1 ELSE 0\n", 55 | " END) AS silver_count,\n", 56 | " SUM(CASE\n", 57 | " WHEN Medal = \"Bronze\" THEN 1 ELSE 0\n", 58 | " END) AS bronze_count\n", 59 | " FROM\n", 60 | " summer_events\n", 61 | " GROUP BY\n", 62 | " Year \n", 63 | " ''')" 64 | ] 65 | }, 66 | { 67 | "cell_type": "code", 68 | "execution_count": 3, 69 | "id": "incredible-trunk", 70 | "metadata": {}, 71 | "outputs": [], 72 | "source": [ 73 | "#Winter Olympics:\n", 74 | "winter_medal_count = pysqldf('''\n", 75 | " SELECT\n", 76 | " Year,\n", 77 | " COUNT(*) AS total_count,\n", 78 | " SUM(CASE\n", 79 | " WHEN Medal IS NOT NULL THEN 1 ELSE 0\n", 80 | " END) AS medal_count,\n", 81 | " SUM(CASE\n", 82 | " WHEN Medal = \"Gold\" THEN 1 ELSE 0\n", 83 | " END) AS gold_count,\n", 84 | " SUM(CASE\n", 85 | " WHEN Medal = \"Silver\" THEN 1 ELSE 0\n", 86 | " END) AS silver_count,\n", 87 | " SUM(CASE\n", 88 | " WHEN Medal = \"Bronze\" THEN 1 ELSE 0\n", 89 | " END) AS bronze_count\n", 90 | " FROM\n", 91 | " winter_events\n", 92 | " GROUP BY\n", 93 | " Year \n", 94 | " ''')" 95 | ] 96 | }, 97 | { 98 | "cell_type": "markdown", 99 | "id": "enabling-comparison", 100 | "metadata": {}, 101 | "source": [ 102 | "I just created two tables to count the total number of medals in the winter and summer olympics. I will calculate the Pearon correlation coefficient between the total number of medals in the winter and summer olympics." 103 | ] 104 | }, 105 | { 106 | "cell_type": "code", 107 | "execution_count": 5, 108 | "id": "behavioral-header", 109 | "metadata": {}, 110 | "outputs": [ 111 | { 112 | "name": "stdout", 113 | "output_type": "stream", 114 | "text": [ 115 | " Year total_count medal_count gold_count silver_count bronze_count\n", 116 | "0 1896 380 143 62 43 38\n", 117 | "1 1900 1936 604 201 228 175\n", 118 | "2 1904 1301 486 173 163 150\n", 119 | "3 1906 1733 458 157 156 145\n", 120 | "4 1908 3101 831 294 281 256\n" 121 | ] 122 | } 123 | ], 124 | "source": [ 125 | "print(summer_medal_count.head())\n" 126 | ] 127 | }, 128 | { 129 | "cell_type": "code", 130 | "execution_count": 6, 131 | "id": "medical-destiny", 132 | "metadata": {}, 133 | "outputs": [ 134 | { 135 | "name": "stdout", 136 | "output_type": "stream", 137 | "text": [ 138 | " Year total_count medal_count gold_count silver_count bronze_count\n", 139 | "0 1924 460 130 55 38 37\n", 140 | "1 1928 582 89 30 28 31\n", 141 | "2 1932 352 92 32 32 28\n", 142 | "3 1936 895 108 36 37 35\n", 143 | "4 1948 1075 135 41 48 46\n" 144 | ] 145 | } 146 | ], 147 | "source": [ 148 | "print(winter_medal_count.head())" 149 | ] 150 | }, 151 | { 152 | "cell_type": "code", 153 | "execution_count": 9, 154 | "id": "finnish-qatar", 155 | "metadata": {}, 156 | "outputs": [ 157 | { 158 | "name": "stdout", 159 | "output_type": "stream", 160 | "text": [ 161 | " Year total_count medal_count gold_count silver_count bronze_count\n", 162 | "0 1896 380 143 62 43 38\n", 163 | "1 1900 1936 604 201 228 175\n", 164 | "2 1904 1301 486 173 163 150\n", 165 | "3 1906 1733 458 157 156 145\n", 166 | "4 1908 3101 831 294 281 256\n", 167 | "5 1912 4040 941 326 315 300\n", 168 | "6 1920 4292 1308 493 448 367\n", 169 | "7 1924 5233 832 277 281 274\n", 170 | "8 1928 4992 734 245 239 250\n", 171 | "9 1932 2969 647 229 214 204\n", 172 | "10 1936 6506 917 312 310 295\n", 173 | "11 1948 6405 852 289 284 279\n", 174 | "12 1952 8270 897 306 291 300\n", 175 | "13 1956 5127 893 302 293 298\n", 176 | "14 1960 8119 911 309 294 308\n", 177 | "15 1964 7702 1029 347 339 343\n", 178 | "16 1968 8588 1057 359 340 358\n", 179 | "17 1972 10304 1215 404 392 419\n", 180 | "18 1976 8641 1320 438 434 448\n", 181 | "19 1980 7191 1384 457 458 469\n", 182 | "20 1984 9454 1476 497 477 502\n", 183 | "21 1988 12037 1582 520 513 549\n", 184 | "22 1992 12977 1712 559 549 604\n", 185 | "23 1996 13780 1842 608 605 629\n", 186 | "24 2000 13821 2004 663 661 680\n", 187 | "25 2004 13443 2001 664 660 677\n", 188 | "26 2008 13602 2048 671 667 710\n", 189 | "27 2012 12920 1941 632 630 679\n", 190 | "28 2016 13688 2023 665 655 703\n" 191 | ] 192 | } 193 | ], 194 | "source": [ 195 | "print(summer_medal_count)" 196 | ] 197 | }, 198 | { 199 | "cell_type": "markdown", 200 | "id": "welsh-ethiopia", 201 | "metadata": {}, 202 | "source": [ 203 | "The length of the array of the number of medal count in the winter Olympics and summer Olympics are different because Winter olympics started in 1924, but Summer olympics started in 1896. Therefore I have to create a new shortened table of the summer olympics started in 1924 to match the length of the winter olympics." 204 | ] 205 | }, 206 | { 207 | "cell_type": "code", 208 | "execution_count": 10, 209 | "id": "modified-serve", 210 | "metadata": {}, 211 | "outputs": [], 212 | "source": [ 213 | "summer_medal_count_new = summer_medal_count[7:]" 214 | ] 215 | }, 216 | { 217 | "cell_type": "code", 218 | "execution_count": 11, 219 | "id": "fossil-gravity", 220 | "metadata": {}, 221 | "outputs": [ 222 | { 223 | "name": "stdout", 224 | "output_type": "stream", 225 | "text": [ 226 | " Year total_count medal_count gold_count silver_count bronze_count\n", 227 | "7 1924 5233 832 277 281 274\n", 228 | "8 1928 4992 734 245 239 250\n", 229 | "9 1932 2969 647 229 214 204\n", 230 | "10 1936 6506 917 312 310 295\n", 231 | "11 1948 6405 852 289 284 279\n", 232 | "12 1952 8270 897 306 291 300\n", 233 | "13 1956 5127 893 302 293 298\n", 234 | "14 1960 8119 911 309 294 308\n", 235 | "15 1964 7702 1029 347 339 343\n", 236 | "16 1968 8588 1057 359 340 358\n", 237 | "17 1972 10304 1215 404 392 419\n", 238 | "18 1976 8641 1320 438 434 448\n", 239 | "19 1980 7191 1384 457 458 469\n", 240 | "20 1984 9454 1476 497 477 502\n", 241 | "21 1988 12037 1582 520 513 549\n", 242 | "22 1992 12977 1712 559 549 604\n", 243 | "23 1996 13780 1842 608 605 629\n", 244 | "24 2000 13821 2004 663 661 680\n", 245 | "25 2004 13443 2001 664 660 677\n", 246 | "26 2008 13602 2048 671 667 710\n", 247 | "27 2012 12920 1941 632 630 679\n", 248 | "28 2016 13688 2023 665 655 703\n" 249 | ] 250 | } 251 | ], 252 | "source": [ 253 | "print(summer_medal_count_new)" 254 | ] 255 | }, 256 | { 257 | "cell_type": "markdown", 258 | "id": "blocked-newspaper", 259 | "metadata": {}, 260 | "source": [ 261 | "I then calculate the Pearon correlation coefficient between the total number of medals in the winter and summer olympics from 1924 to 2016." 262 | ] 263 | }, 264 | { 265 | "cell_type": "code", 266 | "execution_count": 12, 267 | "id": "regional-netherlands", 268 | "metadata": {}, 269 | "outputs": [], 270 | "source": [ 271 | "import numpy as np" 272 | ] 273 | }, 274 | { 275 | "cell_type": "code", 276 | "execution_count": 13, 277 | "id": "cognitive-hello", 278 | "metadata": {}, 279 | "outputs": [], 280 | "source": [ 281 | "x_simple = winter_medal_count.medal_count\n", 282 | "y_simple = summer_medal_count_new.medal_count\n", 283 | "my_rho = np.corrcoef(x_simple, y_simple)" 284 | ] 285 | }, 286 | { 287 | "cell_type": "code", 288 | "execution_count": 14, 289 | "id": "hidden-tragedy", 290 | "metadata": {}, 291 | "outputs": [ 292 | { 293 | "name": "stdout", 294 | "output_type": "stream", 295 | "text": [ 296 | "[[1. 0.94141801]\n", 297 | " [0.94141801 1. ]]\n" 298 | ] 299 | } 300 | ], 301 | "source": [ 302 | "print(my_rho)" 303 | ] 304 | }, 305 | { 306 | "cell_type": "markdown", 307 | "id": "proprietary-probe", 308 | "metadata": {}, 309 | "source": [ 310 | "The Pearon correlation coefficient between the total number of medals in the winter and summer olympics from 1924 to 2016, is 0.94, which is highly positive. Therefore, the performance of a country in winter olympics is highly correlated to that in summer olympics" 311 | ] 312 | }, 313 | { 314 | "cell_type": "markdown", 315 | "id": "related-celtic", 316 | "metadata": {}, 317 | "source": [ 318 | "I will then calculate the standard deviation in country performance through years. A Comparison between average std of Winter and that of Summer Olympics will help." 319 | ] 320 | }, 321 | { 322 | "cell_type": "code", 323 | "execution_count": 15, 324 | "id": "talented-foundation", 325 | "metadata": {}, 326 | "outputs": [], 327 | "source": [ 328 | "std_medal_count_summer_olympics = np.std(y_simple)\n", 329 | "std_medal_count_winter_olympics = np.std(x_simple)\n" 330 | ] 331 | }, 332 | { 333 | "cell_type": "code", 334 | "execution_count": 17, 335 | "id": "unlike-tackle", 336 | "metadata": {}, 337 | "outputs": [ 338 | { 339 | "name": "stdout", 340 | "output_type": "stream", 341 | "text": [ 342 | "std_medal_count_summer_olympics = 475.323015441357\n", 343 | "std_medal_count_winter_olympics = 152.56899942903493\n" 344 | ] 345 | } 346 | ], 347 | "source": [ 348 | "print(\"std_medal_count_summer_olympics =\",std_medal_count_summer_olympics)\n", 349 | "print(\"std_medal_count_winter_olympics =\",std_medal_count_winter_olympics)" 350 | ] 351 | }, 352 | { 353 | "cell_type": "markdown", 354 | "id": "personalized-forum", 355 | "metadata": {}, 356 | "source": [ 357 | "From 1924 to 2016, as the standard deviation in the summer olympics is about 3 times that in the winter olympics, country performance by year change more in Summer Olympics." 358 | ] 359 | }, 360 | { 361 | "cell_type": "code", 362 | "execution_count": null, 363 | "id": "critical-society", 364 | "metadata": {}, 365 | "outputs": [], 366 | "source": [] 367 | } 368 | ], 369 | "metadata": { 370 | "kernelspec": { 371 | "display_name": "Python 3", 372 | "language": "python", 373 | "name": "python3" 374 | }, 375 | "language_info": { 376 | "codemirror_mode": { 377 | "name": "ipython", 378 | "version": 3 379 | }, 380 | "file_extension": ".py", 381 | "mimetype": "text/x-python", 382 | "name": "python", 383 | "nbconvert_exporter": "python", 384 | "pygments_lexer": "ipython3", 385 | "version": "3.7.7" 386 | } 387 | }, 388 | "nbformat": 4, 389 | "nbformat_minor": 5 390 | } 391 | -------------------------------------------------------------------------------- /C4-SQL-for-Data-Science-Capstone-Project/SportsStats/week4_presentation.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/urbanclimatefr/Coursera-Learn-SQL-Basics-for-Data-Science/844aaf928966f21e0d6a04a6cb76a2e4dba4c7eb/C4-SQL-for-Data-Science-Capstone-Project/SportsStats/week4_presentation.pptx -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Tin-Yuet Chung 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Learn SQL Basics for Data Science Specialization 2 | 3 | This repository contains the materials to "Learn SQL Basics for Data Science", a specialization provided by University of California, Davis through Coursera. 4 | 5 | This Specialization is intended for a learner with no previous coding experience seeking to develop SQL query fluency. Through four progressively more difficult SQL projects with data science applications, you will cover topics such as SQL basics, data wrangling, SQL analysis, AB testing, distributed computing using Apache Spark, and more. These topics will prepare you to apply SQL creatively to analyze and explore data; demonstrate efficiency in writing queries; create data analysis datasets; conduct feature engineering, use SQL with other data analysis and machine learning toolsets; and use SQL with unstructured data sets. 6 | 7 | * Course 1: SQL for Data Science 8 | * Course 2: Data Wrangling, Analysis and AB Testing with SQL 9 | * Course 3: Distributed Computing with Spark SQL 10 | * Course 4: SQL for Data Science Capstone Project 11 | --------------------------------------------------------------------------------