{
 "id": "slow_movers",
 "title": "Which products stopped selling, and how much did they used to bring in?",
 "question": "Which products had no sale in the last 90 days, what did they bring in, and does the busy autumn hide more stops?",
 "source": {
  "name": "UCI Online Retail II",
  "publisher": "Chen, D. (2012), UCI Machine Learning Repository",
  "url": "https://archive.ics.uci.edu/dataset/502/online+retail+ii",
  "license": "CC BY 4.0",
  "as_of": "December 2011",
  "rows_raw": 1067371,
  "rows_used": 1021254,
  "caveat": "A UK online gift retailer selling mostly to wholesale customers. The data has sales, not stock levels, and the shop's busiest season falls in the final 90 days."
 },
 "windows": {
  "prior_90": "Jun 13 to Sep 10, 2011",
  "final_90": "Sep 11 to Dec 9, 2011",
  "same_weeks_2010": "Sep 11 to Dec 9, 2010",
  "data_first": "2009-12-01",
  "data_last": "2011-12-09 12:50:00"
 },
 "numbers": {
  "products": 4725,
  "codes_in_clean": 4739,
  "cancel_only_products": 14,
  "cancel_only_revenue": -263.88,
  "codes_as_written": 4909,
  "revenue_total": 18927699.53,
  "revenue_prior": 2041372.87,
  "revenue_final": 3696937.98,
  "sold_in_prior": 3006,
  "stopped_share_products": 33.2,
  "stopped_share_revenue": 8.3,
  "stopped_revenue": 1575750.84,
  "stopped_before_2011": {
   "products": 1009,
   "revenue": 778363.46
  },
  "stopped_in_2011": {
   "products": 558,
   "revenue": 797387.38
  },
  "recent_stop": {
   "products": 206,
   "prior_rev": 22776.83,
   "share_of_prior": 1.1
  },
  "top12_revenue": 181344.08,
  "top1_share_of_stopped": 1.6,
  "slowing_top10_drop": 64373.81,
  "slowing_all_drop": 170821.18,
  "slowing_prior": 244085.73,
  "slowing_final": 73264.55,
  "edge": {
   "sold_both_prior_rev_not_positive": 8,
   "stopped_final_net_negative": 4,
   "steady_not_sold_in_prior": 149,
   "steady_sold_in_prior": 2453,
   "steady_growing": 1947,
   "first_sale_in_first_month": 3009
  }
 },
 "groups": [
  [
   "Stopped",
   1567,
   33.2,
   1575750.84,
   8.3,
   22672.63,
   -23.09,
   1057578
  ],
  [
   "Slowing",
   347,
   7.3,
   1331743.44,
   7.0,
   244085.73,
   73264.55,
   747314
  ],
  [
   "Steady or growing",
   2602,
   55.1,
   15714923.34,
   83.0,
   1774614.51,
   3318414.61,
   9177032
  ],
  [
   "New",
   209,
   4.4,
   305281.91,
   1.6,
   0.0,
   305281.91,
   206120
  ]
 ],
 "last_sale_by_month": [
  [
   "2009-12",
   130,
   8235.19
  ],
  [
   "2010-01",
   79,
   18728.96
  ],
  [
   "2010-02",
   57,
   16854.62
  ],
  [
   "2010-03",
   115,
   64274.66
  ],
  [
   "2010-04",
   61,
   31216.85
  ],
  [
   "2010-05",
   56,
   42591.87
  ],
  [
   "2010-06",
   58,
   45239.54
  ],
  [
   "2010-07",
   43,
   51643.75
  ],
  [
   "2010-08",
   73,
   88755.66
  ],
  [
   "2010-09",
   65,
   89404.1
  ],
  [
   "2010-10",
   78,
   83273.06
  ],
  [
   "2010-11",
   112,
   120304.4
  ],
  [
   "2010-12",
   82,
   117840.8
  ],
  [
   "2011-01",
   41,
   79933.75
  ],
  [
   "2011-02",
   36,
   63090.4
  ],
  [
   "2011-03",
   68,
   108607.27
  ],
  [
   "2011-04",
   100,
   115010.64
  ],
  [
   "2011-05",
   76,
   153288.67
  ],
  [
   "2011-06",
   64,
   56506.5
  ],
  [
   "2011-07",
   78,
   78474.24
  ],
  [
   "2011-08",
   72,
   99616.61
  ],
  [
   "2011-09",
   23,
   42859.3
  ]
 ],
 "top_stopped": [
  [
   "Tea time cake stand in gift box",
   "37503",
   "2010-08-01",
   24912.88,
   2465,
   "2009-12-01"
  ],
  [
   "Red retrospot traditional teapot",
   "21527",
   "2011-05-15",
   23634.99,
   3345,
   "2009-12-01"
  ],
  [
   "English rose design quilted throw",
   "84467",
   "2010-07-27",
   17397.76,
   816,
   "2009-12-06"
  ],
  [
   "Set of 3 coloured  flying ducks",
   "35004C",
   "2011-03-07",
   15791.3,
   3062,
   "2009-12-01"
  ],
  [
   "Set/3 russian doll stacking tins",
   "85232B",
   "2011-02-11",
   14084.25,
   3086,
   "2009-12-01"
  ],
  [
   "Grow your own plant in a can",
   "22444",
   "2011-05-19",
   13714.1,
   10132,
   "2010-03-23"
  ],
  [
   "Tea time tea towels",
   "47556B",
   "2011-04-18",
   13312.06,
   5205,
   "2009-12-01"
  ],
  [
   "Paper bunting coloured lace",
   "22088",
   "2011-07-06",
   12878.83,
   4399,
   "2009-12-01"
  ],
  [
   "Large popcorn holder",
   "22198",
   "2011-02-21",
   12412.31,
   7331,
   "2009-12-01"
  ],
  [
   "White cherry lights",
   "79323W",
   "2010-09-16",
   11627.62,
   3004,
   "2009-12-01"
  ],
  [
   "Antique lily fairy lights",
   "85042",
   "2010-11-16",
   11477.16,
   2685,
   "2009-12-01"
  ],
  [
   "Jumbo bag charlie and lola toys",
   "21033",
   "2011-09-08",
   10100.82,
   4590,
   "2009-12-01"
  ]
 ],
 "slowing_top": [
  [
   "Party bunting",
   "47566",
   34182.18,
   12619.58,
   21562.6
  ],
  [
   "Regency teapot roses",
   "23173",
   14543.68,
   5531.6,
   9012.08
  ],
  [
   "Large zinc heart wall organiser",
   "23134",
   4833.48,
   8.25,
   4825.23
  ],
  [
   "Set 40 heart shape petit four cases",
   "23297",
   5772.53,
   976.8,
   4795.73
  ],
  [
   "Regency sugar bowl green",
   "23174",
   6903.33,
   2459.03,
   4444.3
  ],
  [
   "Picnic basket wicker large",
   "22501",
   5131.73,
   820.61,
   4311.12
  ],
  [
   "3 hook photo shelf antique white",
   "22171",
   5597.25,
   1326.81,
   4270.44
  ],
  [
   "Small zinc heart wall organiser",
   "23135",
   4316.96,
   259.06,
   4057.9
  ],
  [
   "Assorted colours silk fan",
   "15036",
   5483.02,
   1787.85,
   3695.17
  ],
  [
   "Paper bunting retrospot",
   "22090",
   6262.95,
   2863.71,
   3399.24
  ]
 ],
 "season": {
  "window_totals": {
   "prior_90": 2041372.87,
   "final_90": 3696937.98,
   "same_weeks_2010": 3489327.87,
   "final_over_prior": 1.81,
   "final_over_2010": 1.06
  },
  "prior_vs_final": {
   "products": 3006,
   "revenue": 2041516.47,
   "groups": [
    [
     "Stopped",
     206,
     6.9,
     22776.83,
     1.1
    ],
    [
     "Slowing",
     347,
     11.5,
     244085.73,
     12.0
    ],
    [
     "Steady or growing",
     2453,
     81.6,
     1774653.91,
     86.9
    ]
   ]
  },
  "same_season": {
   "products": 3251,
   "revenue": 3489591.06,
   "groups": [
    [
     "Stopped",
     794,
     24.4,
     254325.51,
     7.3
    ],
    [
     "Slowing",
     745,
     22.9,
     1010590.75,
     29.0
    ],
    [
     "Steady or growing",
     1712,
     52.7,
     2224674.8,
     63.8
    ]
   ]
  },
  "stopped_that_sold_in_2010_weeks": {
   "products": 794,
   "share_of_stopped": 50.7,
   "revenue": 1163631.0,
   "revenue_in_2010_weeks": 254325.51
  },
  "stopped_without_2010_weeks_sale": {
   "products": 773,
   "revenue": 412119.84
  }
 },
 "kpis": [
  {
   "label": "Autumn 2010 revenue from products with no sale in autumn 2011",
   "value": "7.3%",
   "note": "£254K; 794 of 3,251 products, Sep 11 to Dec 9"
  },
  {
   "label": "Revenue from products that stopped selling",
   "value": "8.3%",
   "note": "£1.58M of £18.93M, Dec 2009 to Dec 2011"
  },
  {
   "label": "Products that stopped selling",
   "value": "1,567",
   "note": "of 4,725 products with a sale; none in the last 90 days"
  },
  {
   "label": "Prior-90 revenue from products that then stopped",
   "value": "1.1%",
   "note": "206 products sold in the prior 90 days and not in the final 90"
  }
 ],
 "sample_queries": [
  {
   "label": "Products by what happened in the last 90 days",
   "sql": "-- Products by what happened in the last 90 days (Live SQL table: Dec 2010 to Dec 2011)\nWITH p AS (\n    SELECT upper(stock_code) AS code,\n           min(invoice_date) FILTER (WHERE NOT is_cancelled) AS first_sale,\n           count(*) FILTER (WHERE NOT is_cancelled AND invoice_date BETWEEN DATE '2011-06-13' AND DATE '2011-09-10') AS sales_prior,\n           count(*) FILTER (WHERE NOT is_cancelled AND invoice_date >= DATE '2011-09-11') AS sales_final,\n           sum(line_revenue) FILTER (WHERE invoice_date BETWEEN DATE '2011-06-13' AND DATE '2011-09-10') AS rev_prior,\n           sum(line_revenue) FILTER (WHERE invoice_date >= DATE '2011-09-11') AS rev_final,\n           sum(line_revenue) AS rev_total\n    FROM retail_orders\n    GROUP BY 1\n    HAVING count(*) FILTER (WHERE NOT is_cancelled) > 0          -- at least one sale\n), g AS (\n    SELECT *,\n           CASE WHEN sales_final = 0 THEN '1 Stopped'\n                WHEN first_sale >= DATE '2011-09-11' THEN '4 New'\n                WHEN sales_prior > 0 AND rev_prior > 0 AND rev_final < 0.5 * rev_prior THEN '2 Slowing'\n                ELSE '3 Steady or growing' END AS grp\n    FROM p\n)\nSELECT grp AS product_group,\n       count(*) AS products,\n       round(sum(rev_total)) AS revenue_gbp,\n       round(100.0 * sum(rev_total) / sum(sum(rev_total)) OVER (), 1) AS pct_of_revenue\nFROM g\nGROUP BY 1\nORDER BY 1",
   "live_output": {
    "columns": [
     "product_group",
     "products",
     "revenue_gbp",
     "pct_of_revenue"
    ],
    "rows": [
     [
      "1 Stopped",
      640,
      186205.0,
      1.9
     ],
     [
      "2 Slowing",
      347,
      737143.0,
      7.5
     ],
     [
      "3 Steady or growing",
      2583,
      8542619.0,
      87.4
     ],
     [
      "4 New",
      228,
      305561.0,
      3.1
     ]
    ]
   }
  },
  {
   "label": "Top ten products that stopped selling, by past revenue",
   "sql": "-- The ten products that stopped selling and brought in the most (Live SQL table: Dec 2010 to Dec 2011)\nSELECT upper(stock_code) AS code,\n       max(invoice_date) FILTER (WHERE NOT is_cancelled) AS last_sale,\n       round(sum(line_revenue)) AS revenue_gbp\nFROM retail_orders\nGROUP BY 1\nHAVING count(*) FILTER (WHERE NOT is_cancelled) > 0\n   AND count(*) FILTER (WHERE NOT is_cancelled AND invoice_date >= DATE '2011-09-11') = 0\nORDER BY sum(line_revenue) DESC\nLIMIT 10",
   "live_output": {
    "columns": [
     "code",
     "last_sale",
     "revenue_gbp"
    ],
    "rows": [
     [
      "47556B",
      "2011-04-18",
      6045.0
     ],
     [
      "22783",
      "2011-06-14",
      5961.0
     ],
     [
      "22088",
      "2011-07-06",
      5512.0
     ],
     [
      "21033",
      "2011-09-08",
      4850.0
     ],
     [
      "21658",
      "2011-08-11",
      3585.0
     ],
     [
      "85132C",
      "2011-09-02",
      3577.0
     ],
     [
      "22926",
      "2011-05-10",
      3568.0
     ],
     [
      "21527",
      "2011-05-15",
      3465.0
     ],
     [
      "22760",
      "2011-09-05",
      3417.0
     ],
     [
      "22855",
      "2011-08-30",
      3287.0
     ]
    ]
   }
  }
 ],
 "full_history_sql": "-- The same four groups on the full history (retail_lines = the cleaned table, Dec 2009 to Dec 2011)\nWITH p AS (\n    SELECT upper(stock_code) AS code,\n           min(invoice_date) FILTER (WHERE NOT is_cancelled) AS first_sale,\n           count(*) FILTER (WHERE NOT is_cancelled AND invoice_date >= TIMESTAMP '2011-06-13' AND invoice_date < TIMESTAMP '2011-09-11') AS sales_prior,\n           count(*) FILTER (WHERE NOT is_cancelled AND invoice_date >= TIMESTAMP '2011-09-11') AS sales_final,\n           sum(line_revenue) FILTER (WHERE invoice_date >= TIMESTAMP '2011-06-13' AND invoice_date < TIMESTAMP '2011-09-11') AS rev_prior,\n           sum(line_revenue) FILTER (WHERE invoice_date >= TIMESTAMP '2011-09-11') AS rev_final,\n           sum(line_revenue) AS rev_total\n    FROM retail_lines\n    GROUP BY 1\n    HAVING count(*) FILTER (WHERE NOT is_cancelled) > 0\n)\nSELECT CASE WHEN sales_final = 0 THEN 'Stopped'\n            WHEN first_sale >= TIMESTAMP '2011-09-11' THEN 'New'\n            WHEN sales_prior > 0 AND rev_prior > 0 AND 2 * round(rev_final * 100) < round(rev_prior * 100) THEN 'Slowing'\n            ELSE 'Steady or growing' END AS grp,\n       count(*) AS products, round(sum(rev_total), 2) AS revenue\nFROM p GROUP BY 1",
 "live_table": {
  "rows": 531205,
  "first": "2010-12-01",
  "last": "2011-12-09"
 },
 "cleaning": [
  "Dropped non-product stock codes (POST, DOT, M, m, D, BANK CHARGES, AMAZONFEE, C2, PADS, CRUK, ADJUST, ADJUST2, S, B, TEST001/002, gift card vouchers) that represent postage, fees, manual adjustments, and test rows rather than real merchandise.",
  "Dropped rows with price <= 0 (6,207 rows); nearly all of these have no Customer ID and are internal adjustments, not customer sales.",
  "Dropped negative-quantity rows on invoices that do not start with 'C' (3,457 rows); a true return in this dataset is a cancellation invoice (prefix 'C').",
  "Removed 34,035 exact duplicate line items (after the rules above).",
  "A product is a stock code, upper-cased (so 85123a and 85123A are one product). One product can carry more than one code, or be relaunched under a new code, and the data cannot tell.",
  "A sale is a line on an invoice that is not a cancellation. Revenue is net of cancellations: cancellation lines (invoices starting with C) are negative and count against the date of the cancellation.",
  "Windows: final 90 days Sep 11 to Dec 9, 2011 (the last invoice is Dec 9 at 12:50); prior 90 days Jun 13 to Sep 10, 2011; the same weeks a year earlier Sep 11 to Dec 9, 2010.",
  "Stopped: sold earlier, no sale in the final 90 days. Slowing: sold in both windows and final-90 revenue under half of prior-90 revenue (prior-90 revenue above zero). New: first sale in the final 90 days. Steady or growing: the rest that sold in the final 90 days.",
  "14 stock codes have only cancellation lines (net £263.88 below zero): they have no sale, so they are in no group and not in the totals."
 ],
 "checks": [
  "The cleaning reproduces the live Online retail page: 1,067,371 source rows and 1,021,254 after cleaning; the last invoice is Dec 9, 2011 at 12:50.",
  "Every number on this page was recomputed by separate code (verify_slow.py: plain Python reading the original UCI zip, with no DuckDB and no intermediate files) and matches, product by product.",
  "The two queries below were run on the Live SQL table (13 months) in DuckDB 1.5.5 and return the figures shown under them; the full-history SQL was run on the cleaned table and returns the group counts and revenue on this page."
 ]
}