1

Sample table data:

+---------+--------+-------+---------------------+----------+
|   ref   |  cost  | stock |        date         | location |
+---------+--------+-------+---------------------+----------+
| 00AD075 | 352.33 |     6 | 2017-06-14 08:24:43 | WA       |
| 00AD075 | 352.33 |     4 | 2017-06-19 06:01:14 | WA       |
| 00AD075 | 352.33 |     0 | 2017-06-22 00:00:00 | WA       |
| 00AE912 | 231.46 |     2 | 2017-06-14 08:24:43 | WA       |
| 00AE912 | 231.46 |     1 | 2017-06-15 06:31:03 | WA       |
| 00AE912 | 231.46 |     2 | 2017-06-16 06:01:16 | NY       |
| 00AE912 | 231.46 |     0 | 2017-06-19 00:00:00 | WA       |
| 00AE938 | 852.25 |     2 | 2017-06-14 08:24:43 | NY       |
| 00AG510 | 172.27 |     1 | 2017-06-14 08:24:43 | NY       |
| 00AG520 | 359.67 |     6 | 2017-06-14 08:24:43 | NY       |
| 00AG590 | 747.21 |     1 | 2017-06-14 08:24:43 | CA       |
| 00AG590 | 550.00 |     1 | 2017-06-15 06:31:03 | CA       |
+---------+--------+-------+---------------------+----------+

pseduo:

  • fetch all where ref LIKE '00%' AND stock > 0
  • order by date DESC
  • Keep the most recent and discard all other rows with same location
  • if stock not greater than 0 discard it too

Expected data:

+----------+----------+---------+-----------------------+-----+
| 00AD075  |  352.33  |      4  |  2017-06-19 06:01:14  |  WA |
+----------+----------+---------+-----------------------+-----+
| 00AE912  |  231.46  |      2  |  2017-06-16 06:01:16  |  NY |
| 00AE938  |  852.25  |      2  |  2017-06-14 08:24:43  |  NY |
| 00AG510  |  172.27  |      1  |  2017-06-14 08:24:43  |  NY |
| 00AG520  |  359.67  |      6  |  2017-06-14 08:24:43  |  NY |
| 00AG590  |  550.00  |      1  |  2017-06-15 06:31:03  |  CA |
+----------+----------+---------+-----------------------+-----+

So there are multiple rows for each ref, based on the date. I need to select the most recent row. This is what I'm doing, but it gives me an error:

SELECT DISTINCT
    * 
FROM
    inventory 
WHERE
    ref LIKE '00%' 
    AND stock > 0 
GROUP BY
    ref 
ORDER BY
    date

Error:

1055 - Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'inventory.scost' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by, Time: 0.319000s

eozzy
  • 66,048
  • 104
  • 272
  • 428
  • where is `'00%'` in your table? – Damien Jun 19 '17 at 03:19
  • 1
    what's the error? – ChickenFeet Jun 19 '17 at 03:32
  • @DamienGold doesnt it mean `ref` that begins with `00` – eozzy Jun 19 '17 at 04:08
  • @ChickenFeet `1055 - Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'app.inventory.scost' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by, Time: 0.319000s` – eozzy Jun 19 '17 at 04:09
  • Looks like the `sql_mode=only_full_group_by` cause the issue. https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_only_full_group_by – ajreal Jun 19 '17 at 04:36

2 Answers2

3

Updated One way of doing it with strict mode turned on

SELECT i.* 
  FROM inventory i JOIN (
    -- fetch the ref and the max date
    SELECT ref, MAX(date) date
      FROM inventory
     WHERE ref LIKE '00%'
       AND stock > 0
     GROUP BY ref
 ) q -- then join back to grab all other columns
    ON i.ref = q.ref
   AND i.date = q.date
 ORDER BY date, ref

or alternatively you can emulate ROW_NUMBER() OVER (PARTITION BY ref ORDER BY date) with session variables since MySQL doesn't yet support window functions

SELECT ref, cost, stock, date, location
  FROM (
    SELECT *, @rn := IF(@g = ref, @rn + 1, 1) rn, @g := ref
      FROM inventory CROSS JOIN (
        SELECT @rn := 1, @g := NULL
      ) v
     WHERE ref LIKE '00%'
       AND stock > 0
     ORDER BY ref, date DESC
 ) q
 WHERE rn = 1
 ORDER BY date, ref

Output:

+---------+------+-------+---------------------+----------+
| ref     | cost | stock | date                | location |
+---------+------+-------+---------------------+----------+
| 00AE938 |  852 |     2 | 2017-06-14 08:24:43 | NY       |
| 00AG510 |  172 |     1 | 2017-06-14 08:24:43 | NY       |
| 00AG520 |  360 |     6 | 2017-06-14 08:24:43 | NY       |
| 00AG590 |  550 |     1 | 2017-06-15 06:31:03 | CA       |
| 00AE912 |  231 |    20 | 2017-06-16 06:01:16 | WA       |
| 00AD075 |  352 |     4 | 2017-06-19 06:01:14 | WA       |
+---------+------+-------+---------------------+----------+

Here is a dbfiddle demo for both queries

peterm
  • 91,357
  • 15
  • 148
  • 157
  • Since I'm new to MySQL and couldn't understand the query for what its doing, I tried to export the data and verify manually .. and turns out it doesn't choose the latest row. Example: https://pastebin.com/hzcF6ZS1 <-- in this case it gets the older record (2017-06-14) instead of the new one (which it shouldn't get infact because the stock is 0 and fails the condition) – eozzy Jun 19 '17 at 21:35
  • @3zzy It's because I forgot to include the `cost > 0` condition in my examples. Sorry about that. The answer is updated including the dbfiddle demo which now contains some 0 stock entries to illustrate that we're not fetching them. Try it out and let me know if it works as you expect. – peterm Jun 19 '17 at 21:43
  • @3zzy Feel free to ask any follow up question if you'd like to better understand how queries work – peterm Jun 19 '17 at 21:51
  • Thanks, but even in your example `00AE912` the latest stock entry (`2017-06-19`) is 0 but the result still shows an older entry from `2017-06-16` with `20` in stock. So maybe a lil confusion here, this is what I'm looking to do basically: fetch all rows grouped by ref and location, then get the latest row and discard the older entries, on the latest row check if stock > 0. Hope I'm making sense? – eozzy Jun 19 '17 at 22:59
  • @3zzy It is in fact confusing and differs from what you asked originally. Now that being said please edit your question and provide a realistic (reflective of your actual requirements) set of sample data and the **exact** desired output of query. – peterm Jun 19 '17 at 23:32
  • @3zzy BTW if you needed the most recent row per ref regardless of the stock quantity my original query should've worked just fine. I just realized that you might've had the condition in your query and that's why you didn't get the latest row. Now if it's not the case then again you'd need to provide the proper sample data and the exact expected outcome. – peterm Jun 19 '17 at 23:49
  • Thats it really, your query is perfect except that it always selects a row with stock > 0 without checking the date, whereaa I want the most recent stock info. Basically, I'm exporting a report for a product series (starting with 00) that are in stock at any location. – eozzy Jun 20 '17 at 22:08
0
SELECT DISTINCT
    * 
FROM
    inventory 
GROUP BY
    ref 
HAVING 
    ref LIKE '00%' 
    AND stock > 0 
ORDER BY
    date desc

Try this.

Komal K.
  • 450
  • 2
  • 13
  • Same error with your query. `1055 - Expression #2 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'inventory.scost' which is not functionally dependent on columns in GROUP BY clause; this is incompatible with sql_mode=only_full_group_by, Time: 0.274000s` – eozzy Jun 19 '17 at 05:14
  • https://stackoverflow.com/questions/40136012/select-list-contains-nonaggregated-column – Komal K. Jun 19 '17 at 05:17