diff --git a/src/metabase/lib/binning.cljc b/src/metabase/lib/binning.cljc
index 0f42e88235e7bb45f08d6f9cbfa5b005714f12e6..241bb7b4fad1834c33badb7335fdb3f8b7f751f8 100644
--- a/src/metabase/lib/binning.cljc
+++ b/src/metabase/lib/binning.cljc
@@ -147,15 +147,25 @@
   [metadata-providerable :- ::lib.schema.metadata/metadata-providerable
    column-metadata       :- ::lib.schema.metadata/column
    value                 :- number?]
+  ;; TODO: I think this function is taking the wrong approach. It uses the (global) :fingerprint for all cases, and if
+  ;; we're looking at nested bins (eg. bin a query, then zoom in on one of those bins) we have tighter min and max
+  ;; bounds on the column's own `binning-options`. We should be using those bounds everywhere if they exist, and falling
+  ;; back on the fingerprint only if they're not defined.
   (when-let [binning-options (binning column-metadata)]
     (case (:strategy binning-options)
       :num-bins
-      (when-let [{min-value :min, max-value :max, :as _number-fingerprint} (get-in column-metadata [:fingerprint :type :type/Number])]
-        (let [{:keys [num-bins]} binning-options
-              bin-width          (lib.binning.util/nicer-bin-width min-value max-value num-bins)]
-          {:bin-width bin-width
-           :min-value value
-           :max-value (+ value bin-width)}))
+      (or ;; If the column is already binned, compute the width of this single bin based on its bounds and width.
+          (when-let [bin-width (:bin-width binning-options)]
+            {:bin-width bin-width
+             :min-value value
+             :max-value (+ value bin-width)})
+          ;; Otherwise use the fingerprint.
+          (when-let [{min-value :min, max-value :max, :as _number-fingerprint} (get-in column-metadata [:fingerprint :type :type/Number])]
+            (let [{:keys [num-bins]} binning-options
+                  bin-width          (lib.binning.util/nicer-bin-width min-value max-value num-bins)]
+              {:bin-width bin-width
+               :min-value value
+               :max-value (+ value bin-width)})))
 
       :bin-width
       (let [{:keys [bin-width]} binning-options]
diff --git a/src/metabase/lib/drill_thru/zoom_in_bins.cljc b/src/metabase/lib/drill_thru/zoom_in_bins.cljc
index 140776767b0556515ff6dfbdd9cbd5c078cba13c..c99d31667a83cc30354b04c700e73f54a0d8de6a 100644
--- a/src/metabase/lib/drill_thru/zoom_in_bins.cljc
+++ b/src/metabase/lib/drill_thru/zoom_in_bins.cljc
@@ -19,8 +19,9 @@
   - Remove breakouts for `dimensions`. Please note that with regular cells and pivot cells it would mean removing all
     breakouts; but with legend item clicks it would remove the breakout for the legend item column only.
 
-  - Add a filter based on columns and values from `dimensions`. Take temporal units and binning strategies into
-    account
+  - Remove any existing filters for this column.
+
+  - Add new filters limiting this column to the range defined by the clicked bin.
     https://github.com/metabase/metabase/blob/0624d8d0933f577cc70c03948f4b57f73fe13ada/frontend/src/metabase-lib/queries/utils/actions.js#L99
 
   - Add a breakout based on the numeric column (from requirements). For location columns, use the binning strategy
@@ -71,6 +72,7 @@
    [metabase.lib.binning :as lib.binning]
    [metabase.lib.breakout :as lib.breakout]
    [metabase.lib.drill-thru.common :as lib.drill-thru.common]
+   [metabase.lib.equality :as lib.equality]
    [metabase.lib.filter :as lib.filter]
    [metabase.lib.remove-replace :as lib.remove-replace]
    [metabase.lib.schema :as lib.schema]
@@ -128,7 +130,11 @@
   [query                                        :- ::lib.schema/query
    stage-number                                 :- :int
    {:keys [column min-value max-value new-binning]} :- ::lib.schema.drill-thru/drill-thru.zoom-in.binning]
-  (-> query
-      (lib.filter/filter stage-number (lib.filter/>= column min-value))
-      (lib.filter/filter stage-number (lib.filter/< column max-value))
-      (update-breakout stage-number column new-binning)))
+  (let [old-filters (filter (fn [[operator _opts filter-column]]
+                              (and (#{:>= :<} operator)
+                                   (lib.equality/find-matching-column filter-column [column])))
+                            (lib.filter/filters query stage-number))]
+    (-> (reduce lib.remove-replace/remove-clause query old-filters)
+        (lib.filter/filter stage-number (lib.filter/>= column min-value))
+        (lib.filter/filter stage-number (lib.filter/< column max-value))
+        (update-breakout stage-number column new-binning))))
diff --git a/test/metabase/lib/drill_thru/zoom_in_bins_test.cljc b/test/metabase/lib/drill_thru/zoom_in_bins_test.cljc
index ed15742854698158033d55154e11445a5048edbc..0e7ab7e672dfa2d748c0e04dfd64de3457f4a9e7 100644
--- a/test/metabase/lib/drill_thru/zoom_in_bins_test.cljc
+++ b/test/metabase/lib/drill_thru/zoom_in_bins_test.cljc
@@ -255,3 +255,41 @@
                         :dimensions [discount-dim]}
           drills       (set (map :type (lib/available-drill-thrus query context)))]
       (is (not (drills :drill-thru/zoom-in.binning))))))
+
+(deftest ^:parallel nested-zoom-test
+  (testing "repeatedly zooming in on smaller bins should work"
+    (let [query (as-> (lib/query meta/metadata-provider (meta/table-metadata :orders)) $q
+                  ;; Filtering like we'd already zoomed in once, on the 40-60 bin.
+                  (lib/filter $q (lib/>= (meta/field-metadata :orders :subtotal) 40))
+                  (lib/filter $q (lib/<  (meta/field-metadata :orders :subtotal) 60))
+                  (lib/aggregate $q (lib/count))
+                  (lib/breakout $q (lib/with-binning (meta/field-metadata :orders :subtotal)
+                                     {:strategy  :num-bins
+                                      :num-bins  8
+                                      :bin-width 2.5
+                                      :min-value 40
+                                      :max-value 60})))]
+      (lib.drill-thru.tu/test-drill-application
+        {:click-type     :cell
+         :query-type     :aggregated
+         :custom-query   query
+         :custom-row     {"count" 100
+                          "SUBTOTAL" 50} ;; Clicking the 50-52.5 bin
+         :column-name    "count"
+         :drill-type     :drill-thru/zoom-in.binning
+         :expected       {:type        :drill-thru/zoom-in.binning
+                          :column      {:name "SUBTOTAL"}
+                          :min-value   50
+                          :max-value   52.5
+                          :new-binning {:strategy :default}}
+         :expected-query {:stages [{:source-table (meta/id :orders)
+                                    :aggregation  [[:count {}]]
+                                    :breakout     [[:field
+                                                    {:binning {:strategy :default}}
+                                                    (meta/id :orders :subtotal)]]
+                                    :filters      [[:>= {}
+                                                    [:field {} (meta/id :orders :subtotal)]
+                                                    50]
+                                                   [:< {}
+                                                    [:field {} (meta/id :orders :subtotal)]
+                                                    52.5]]}]}}))))