From 4add988908a4d68a295aa6461f9c00356356fa0e Mon Sep 17 00:00:00 2001 From: Ian Gulliver Date: Mon, 15 Apr 2019 03:51:32 +0000 Subject: [PATCH] Converting subselects to joins, part 2 --- ...converting-subselects-to-joins-part-2.html | 35 +++++++++++++++++++ index.html | 1 + ...9-converting-subselects-to-joins-part-2.md | 33 +++++++++++++++++ markdown/index.md | 1 + 4 files changed, 70 insertions(+) create mode 100644 2011-11-29-converting-subselects-to-joins-part-2.html create mode 100644 markdown/2011-11-29-converting-subselects-to-joins-part-2.md diff --git a/2011-11-29-converting-subselects-to-joins-part-2.html b/2011-11-29-converting-subselects-to-joins-part-2.html new file mode 100644 index 0000000..40fb4e6 --- /dev/null +++ b/2011-11-29-converting-subselects-to-joins-part-2.html @@ -0,0 +1,35 @@ + + + + + +

I previously discussed this in depth. However, today I saw a case that I didn't cover:

+ +

You have a table of Users and a table of Logins, with a row for each user login event. You're looking for users that have logged in within the last 31 days. The initial version of this I saw used a derived table:

+ +
SELECT
+    UserId,
+    LastLogin
+  FROM Users
+    JOIN (
+      SELECT
+          UserId,
+          DATEDIFF(NOW(), MAX(TimeStamp)) AS LastLogin
+        FROM Logins
+        GROUP BY UserId
+    ) AS Temp USING (UserId)
+  WHERE LastLogin <= 31;
+
+ +

We can convert this to a simple JOIN with the magic of HAVING. HAVING is like WHERE, but applies after aggregation:

+ +
SELECT
+    UserId,
+    DATEDIFF(NOW(), MAX(TimeStamp)) AS LastLogin
+  FROM Users
+    JOIN Logins USING (UserId)
+  GROUP BY UserId
+  HAVING LastLogin <= 31;
+
+ + diff --git a/index.html b/index.html index a5dc2b0..82749c3 100644 --- a/index.html +++ b/index.html @@ -20,6 +20,7 @@
  • 2016-Feb-15: Cable modem channel party
  • 2016-Feb-01: How to enrage your cable modem
  • 2016-Feb-01: Hall of 2.4 GHz Shame, 2016 Edition
  • +
  • 2011-Nov-29: Converting subselects to joins, part 2
  • 2011-Nov-29: Safe(r) data changes
  • 2011-Aug-09: InnoDB as the default table type
  • 2011-Aug-08: Database best practices for future scalability
  • diff --git a/markdown/2011-11-29-converting-subselects-to-joins-part-2.md b/markdown/2011-11-29-converting-subselects-to-joins-part-2.md new file mode 100644 index 0000000..5eb3f29 --- /dev/null +++ b/markdown/2011-11-29-converting-subselects-to-joins-part-2.md @@ -0,0 +1,33 @@ + + + + + +[I previously discussed this in depth](2011-07-12-converting-subselects-to-joins.html). However, today I saw a case that I didn't cover: + +You have a table of Users and a table of Logins, with a row for each user login event. You're looking for users that have logged in within the last 31 days. The initial version of this I saw used a derived table: + + SELECT + UserId, + LastLogin + FROM Users + JOIN ( + SELECT + UserId, + DATEDIFF(NOW(), MAX(TimeStamp)) AS LastLogin + FROM Logins + GROUP BY UserId + ) AS Temp USING (UserId) + WHERE LastLogin <= 31; + +We can convert this to a simple JOIN with the magic of HAVING. HAVING is like WHERE, but applies after aggregation: + + SELECT + UserId, + DATEDIFF(NOW(), MAX(TimeStamp)) AS LastLogin + FROM Users + JOIN Logins USING (UserId) + GROUP BY UserId + HAVING LastLogin <= 31; + + diff --git a/markdown/index.md b/markdown/index.md index 0225a9e..7334a20 100644 --- a/markdown/index.md +++ b/markdown/index.md @@ -19,6 +19,7 @@ 1. 2016-Feb-15: [Cable modem channel party](2016-02-15-cable-modem-channel-party.html) 1. 2016-Feb-01: [How to enrage your cable modem](2016-02-01-how-to-enrage-your-cable-modem.html) 1. 2016-Feb-01: [Hall of 2.4 GHz Shame, 2016 Edition](2016-02-01-hall-of-2-4-ghz-shame-2016-edition.html) +1. 2011-Nov-29: [Converting subselects to joins, part 2](2011-11-29-converting-subselects-to-joins-part-2.html) 1. 2011-Nov-29: [Safe(r) data changes](2011-11-29-safer-data-changes.html) 1. 2011-Aug-09: [InnoDB as the default table type](2011-08-09-innodb-as-the-default-table-type.html) 1. 2011-Aug-08: [Database best practices for future scalability](2011-08-08-database-best-practices-for-future-scalability.html)