then joined them together with flags from the ‘Customers’ table.<\/li><\/ul>\n\n\n\nWhere you see a WITH, is the CTE starting and then I’m naming them ‘sent’ and ‘unsubs’ before starting to tell the CTE what I want to return:<\/p>\n\n\n\n
; with sent as -- start the CTE with a semicolon to terminate anything above\n\n(select \n emailaddress,\n emailid, \n senddate\nfrom\n marketing.emailsent\nwhere\n senddate between '2018-01-01' and '2018-01-31'\n), -- add a comma if you need to add a subsequent CTE\n\nunsubs as\n\n(select \n emailaddress,\n emailid, \n senddate\nfrom\n marketing.emailunsubscribe\nwhere\n senddate between '2018-01-01' and '2018-01-31'\n) -- no comma for the last CTE\n\nselect\n 'January' as monthdelivered,\n c.country, \n count(distinct sent.emailaddress) as countofdelivered, \n count(distinct unsubs.emailaddress) as countofunsubd\nfrom sent\nleft join \n marketing.customers c on sent.email = unsubs.emailaddress\nleft join \n unsubs on sent.email = unsubs.email \n and sent.emailid = unsubs.emailid\n<\/code><\/pre>\n\n\n\nWhen I do the final ‘join everything together’ part I’m joining fields from the ‘sent’ dataset such as ‘sent.email’.<\/p>\n\n\n\n
\n\n\n\nWhy not just use a Subquery?<\/h2>\n\n\n\n
The way I get my head around reading a subquery is by reading from the inside out. It’s nesting everything you need together, but in my opinion, it tends to get ugly really quickly.<\/p>\n\n\n\n
- The first step is to run the query in the centre starting ‘select accountID …’ to get all orders greater than 30 from the ‘OrderHistory’ table.<\/li>
- Then join<\/a> on the ‘account’ table to look up which accounts were from New Zealand.<\/li>
- Then the top select runs to return all the fields from the\u00a0ord<\/em>\u00a0dataset and the three columns I want to see from the account table.<\/li><\/ul>\n\n\n\n
select\n ord.*,\n acc.country\n acc.city\n acc.createddate\nfrom (\n select \n accountid, \n ordered, \n ordervalue\n from \n sales.orderhistory\n where ordervalue > '30'\n ) ord\njoin \n sales.account acc on ord.accountid = acc.accountid\nwhere \n acc.country = 'New Zealand'<\/code><\/pre>\n\n\n\n
\n\n\n\nWhy are they so great?<\/h2>\n\n\n\n
You can use them multiple times throughout your script and they are readable, you can return what you need then reference it later.<\/p>\n\n\n\n
\n\n\n\n
If you don\u2019t have write permissions this may not be possible. And if it’s only used for this query your DBA<\/a> might not be thrilled with you creating one-off tables.<\/p>\n\n\n\n
\n\n\n\nAre there any negatives?<\/h2>\n\n\n\n
CTEs don\u2019t last forever and can only be used in the query you\u2019re currently in, unlike temp tables or views that can survive outside the current script.<\/p>\n\n\n\n
\n\n\n\nThe database<\/a> will always decide the best way to execute your query. If you ask your friendly DBA which strategy to use, they can fill you in on which strategy works best for your database. CTEs are all about readability, so if it works for you give it a try.<\/p>\n\n\n\n
\n\n\n\nPhoto by Adrianna Calvo<\/a><\/strong> from Pexels<\/a><\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"
CTEs are underrated compared to the subquery. Here’s why I prefer to use CTEs when building SQL queries.<\/p>\n","protected":false},"author":1,"featured_media":3045,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"Layout":""},"categories":[214],"tags":[198,199],"yoast_head":"\nWhy I use SQL CTEs | Helen Anderson<\/title>\n<meta name=\"description\" content=\"SQL CTEs are underrated compared to the subquery. Here's why I prefer to use CTEs when building SQL queries.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/helenanderson.co.nz\/sql-ctes\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Why I use SQL CTEs | Helen Anderson\" \/>\n<meta property=\"og:description\" content=\"SQL CTEs are underrated compared to the subquery. Here's why I prefer to use CTEs when building SQL queries.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/helenanderson.co.nz\/sql-ctes\/\" \/>\n<meta property=\"og:site_name\" content=\"Helen Anderson\" \/>\n<meta property=\"article:published_time\" content=\"2018-10-20T03:33:19+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2020-05-14T06:41:50+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/helenanderson.co.nz\/wp-content\/uploads\/2020\/05\/sql-ctes.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1280\" \/>\n\t<meta property=\"og:image:height\" content=\"853\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@helenanders26\" \/>\n<meta name=\"twitter:site\" content=\"@helenanders26\" \/>\n<meta name=\"twitter:label1\" content=\"Est. reading time\">\n\t<meta name=\"twitter:data1\" content=\"3 minutes\">\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebSite\",\"@id\":\"https:\/\/helenanderson.co.nz\/#website\",\"url\":\"https:\/\/helenanderson.co.nz\/\",\"name\":\"Helen Anderson\",\"description\":\"Data Analyst | Technical Writer\",\"publisher\":{\"@id\":\"https:\/\/helenanderson.co.nz\/#\/schema\/person\/4677a271385757403307fb29bd14d7bf\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":\"https:\/\/helenanderson.co.nz\/?s={search_term_string}\",\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"en-NZ\"},{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/helenanderson.co.nz\/sql-ctes\/#primaryimage\",\"inLanguage\":\"en-NZ\",\"url\":\"https:\/\/helenanderson.co.nz\/wp-content\/uploads\/2020\/05\/sql-ctes.jpg\",\"width\":1280,\"height\":853,\"caption\":\"sql ctes subquery\"},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/helenanderson.co.nz\/sql-ctes\/#webpage\",\"url\":\"https:\/\/helenanderson.co.nz\/sql-ctes\/\",\"name\":\"Why I use SQL CTEs | Helen Anderson\",\"isPartOf\":{\"@id\":\"https:\/\/helenanderson.co.nz\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/helenanderson.co.nz\/sql-ctes\/#primaryimage\"},\"datePublished\":\"2018-10-20T03:33:19+00:00\",\"dateModified\":\"2020-05-14T06:41:50+00:00\",\"description\":\"SQL CTEs are underrated compared to the subquery. Here's why I prefer to use CTEs when building SQL queries.\",\"inLanguage\":\"en-NZ\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/helenanderson.co.nz\/sql-ctes\/\"]}]},{\"@type\":\"Article\",\"@id\":\"https:\/\/helenanderson.co.nz\/sql-ctes\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/helenanderson.co.nz\/sql-ctes\/#webpage\"},\"author\":{\"@id\":\"https:\/\/helenanderson.co.nz\/#\/schema\/person\/4677a271385757403307fb29bd14d7bf\"},\"headline\":\"Why I use SQL CTEs\",\"datePublished\":\"2018-10-20T03:33:19+00:00\",\"dateModified\":\"2020-05-14T06:41:50+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/helenanderson.co.nz\/sql-ctes\/#webpage\"},\"publisher\":{\"@id\":\"https:\/\/helenanderson.co.nz\/#\/schema\/person\/4677a271385757403307fb29bd14d7bf\"},\"image\":{\"@id\":\"https:\/\/helenanderson.co.nz\/sql-ctes\/#primaryimage\"},\"keywords\":\"analysis,sql\",\"articleSection\":\"Data Analysis\",\"inLanguage\":\"en-NZ\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/helenanderson.co.nz\/#\/schema\/person\/4677a271385757403307fb29bd14d7bf\",\"name\":\"Helen Anderson\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\/\/helenanderson.co.nz\/#personlogo\",\"inLanguage\":\"en-NZ\",\"url\":\"https:\/\/helenanderson.co.nz\/wp-content\/uploads\/2019\/11\/helen-anderson-profile-selects-FA-1000.jpg\",\"width\":1000,\"height\":1000,\"caption\":\"Helen Anderson\"},\"logo\":{\"@id\":\"https:\/\/helenanderson.co.nz\/#personlogo\"},\"description\":\"Hi, I'm Helen. I'm a data analyst, technical writer, and AWS Data Hero. I interpret the story behind the numbers, build data applications, and grow analyst and developer communities - currently at Kiwibank.\",\"sameAs\":[\"http:\/\/www.helenanderson.co.nz\/\",\"https:\/\/www.instagram.com\/helenanders26\/\",\"https:\/\/www.linkedin.com\/in\/helenanders26\/\",\"https:\/\/twitter.com\/helenanders26\",\"https:\/\/www.youtube.com\/channel\/UCttVhJizwkhgmMlDBMUE0wQ\"]}]}<\/script>\n","_links":{"self":[{"href":"https:\/\/helenanderson.co.nz\/wp-json\/wp\/v2\/posts\/3044"}],"collection":[{"href":"https:\/\/helenanderson.co.nz\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/helenanderson.co.nz\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/helenanderson.co.nz\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/helenanderson.co.nz\/wp-json\/wp\/v2\/comments?post=3044"}],"version-history":[{"count":4,"href":"https:\/\/helenanderson.co.nz\/wp-json\/wp\/v2\/posts\/3044\/revisions"}],"predecessor-version":[{"id":3249,"href":"https:\/\/helenanderson.co.nz\/wp-json\/wp\/v2\/posts\/3044\/revisions\/3249"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/helenanderson.co.nz\/wp-json\/wp\/v2\/media\/3045"}],"wp:attachment":[{"href":"https:\/\/helenanderson.co.nz\/wp-json\/wp\/v2\/media?parent=3044"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/helenanderson.co.nz\/wp-json\/wp\/v2\/categories?post=3044"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/helenanderson.co.nz\/wp-json\/wp\/v2\/tags?post=3044"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}