4

I have subjects table and tutorials table in SQLite database. I am trying to select current tutorial. There are my tables

  • Subjects table:

    -------------------
    |  id |   name    |
    -------------------
    |  1  | Chemistry |
    |  2  | Physic    |
    -------------------
    
  • Tutorials table:

    -----------------------------------------
    | id  |    name   | subj_id | completed |
    -----------------------------------------
    |  1  | chapter 1 |   1     |     1     |
    |  2  | chapter 2 |   1     |     0     |
    |  3  | chapter 3 |   1     |     0     |
    |  4  | chapter 1 |   2     |     1     |
    |  5  | chapter 2 |   2     |     1     |
    |  6  | chapter 3 |   2     |     0     |
    |  7  | chapter 4 |   2     |     0     |
    -----------------------------------------
    

My current eloquent is:

  $query->where('completed', false)->groupBy('subj_id')->get();

And it returns the following:

-----------------------------------------
| id  |    name   | subj_id | completed |
-----------------------------------------
|  3  | chapter 3 |   1     |     0     |
|  7  | chapter 4 |   2     |     0     |
-----------------------------------------

Now I wish to select id 2 and 6.

-----------------------------------------
| id  |    name   | subj_id | completed |
-----------------------------------------
|  2  | chapter 2 |   1     |     0     |
|  6  | chapter 3 |   2     |     0     |
-----------------------------------------

How could I get id 2 and 6 using sqlite?

AstroCB
  • 12,337
  • 20
  • 57
  • 73
Ryan Exlay
  • 361
  • 1
  • 3
  • 12
  • By what logic do you choose 2 & 6 over 3 & 7? – lukasgeiter Apr 19 '15 at 14:02
  • Hi lukas simply id 2 is chapter 2 of chemistry, id 3 is chapter 3 of chemistry. id 1 has completed. So I wish to get current tutorial chapter of chemistry and same to physic subject. – Ryan Exlay Apr 19 '15 at 14:17

3 Answers3

7

My problem is solved by @zerofl4g's help.

This eloquent helped by @zerofl4g.

$query->select(DB::raw("SELECT MIN(id), name, subj_id FROM tutorials
 WHERE completed = 0 GROUP BY subj_id"));

It doesn't work for me but help me a lot. I don't know the precise reason why not worked form me but I think I am using it as subquery. So I got duplicate select and from errors. It must surely work for someone who want to use as single query.

My solution is just select columns with DB::raw and ->from('tutorials') is also optional, as it is subquery of a long query

$query->select(DB::raw('MIN(id) as id, name, subj_id'))->from('tutorials')
->where('completed', false)->groupBy('subj_id');

Final eloquent I am using is

$query->select(DB::raw('MIN(id) as id, name, subj_id'))
->where('completed', false)->groupBy('subj_id');`

Hope to be helpful.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Ryan Exlay
  • 361
  • 1
  • 3
  • 12
4

If you want to return first row in group by, you can try the code below. I think what you want to get is the latest chapter in the subject that not finish.

$data = Tutorial::where('completed', 0)->get();
$groups = $data->groupBy('subj_id');

$results = [];
foreach($groups as $group) {
    $results[] = head($group);
}
return $results;
  1. Get all tutorials row

  2. Then, group by subj_id. The data you get is like below

{
    1: [{
        id: "2",
        name: "chapter 2",
        subj_id: "1",
        completed: "0"
    }, {
        id: "3",
        name: "chapter 3",
        subj_id: "1",
        completed: "0"
    }],

    2: [{
        id: "6",
        name: "chapter 3",
        subj_id: "2",
        completed: "0"
    }, {
        id: "7",
        name: "chapter 4",
        subj_id: "2",
        completed: "0"
    }]
}
  1. Foreach each group and get the minimum id by using head() helper function in laravel.
Gamopo
  • 1,600
  • 1
  • 14
  • 22
Faiz
  • 1,021
  • 9
  • 10
  • Hi zer0fl4g, Thank for your answer. my query is just subquery of long query. I can't use foreach nor any php function. if I run this query `select min(id), name, subj_id from tutorials where completed = 0 group by subj_id` I get the what id 2 and 6. But problem is I don't know how to run that query as subquery. Anyway thank and appreciate your help. – Ryan Exlay Apr 19 '15 at 16:04
  • Can you share your full query – Faiz Apr 19 '15 at 16:15
  • I made easy to understandable small table. `$members = Member::has('lotteries')->with([ 'lotteries'=> function ($query){ $query->select(array('lotteries.id','lotteries.name','basic_amt','lotteries.total_amt')); }, 'lotteries.prizes'=> function($query) { $query ->select(array('prizes.id','prizes.lottery_id','prizes.prize_number','prizes.current_amt')) ->where('completed', false) ->groupBy('lottery_id'); } ])->get(array('members.id','members.name'))->toJSON(); //$members = Member::all(array('id','name'))->toJSON(); return $members;` – Ryan Exlay Apr 19 '15 at 16:19
  • the part what i described is `$query ->select(array('prizes.id','prizes.lottery_id','prizes.prize_number','prizes.current_amt')) ->where('completed', false) ->groupBy('lottery_id');` – Ryan Exlay Apr 19 '15 at 16:20
  • You can try use Raw Queries like this. 'lotteries.prizes'=> function($query) { $query->select(DB::raw("SELECT MIN(id), name, subj_id FROM tutorials WHERE completed = 0 GROUP BY subj_id")); } I already tested it – Faiz Apr 19 '15 at 16:42
  • Hi Zer0fl4g I got this error. becoz two select `"SQLSTATE[HY000]: General error: 1 near \"SELECT\": syntax error (SQL: select SELECT MIN(id),` Thank for your help, bro. I had tried it and I tried again when u suggest. Same error resulted. – Ryan Exlay Apr 19 '15 at 16:49
  • if I run this `select "prizes"."id", "prizes"."lottery_id", "prizes"."prize_number", "prizes"."current_amt" from "prizes" where "prizes"."deleted_at" is null and "prizes"."lottery_id" in ('2', '1', '3') and "completed" = '0' group by "lottery_id"` I get id 3 and 7. This one result 2 and 6 `select MIN("id"), "prizes"."lottery_id", "prizes"."prize_number", "prizes"."current_amt" from "prizes" where "prizes"."deleted_at" is null and "prizes"."lottery_id" in ('2', '1', '3') and "completed" = '0' group by "lottery_id"` – Ryan Exlay Apr 19 '15 at 16:56
  • Why you write two select inside the query. Remove select. You query now "select SELECT MIN(id)". So you must remove select with the lowercase letter. The correct query is "SELECT MIN(id)" – Faiz Apr 19 '15 at 16:57
  • Your problem solved or not? I see you can get result 2 & 6 which means your problem already solved if i refer to your question. – Faiz Apr 19 '15 at 17:01
  • Hi zerofl4g. thank for your help. My problem haven't solved by laravel but I can get what I want, when I test on sqlite query run. but as I said in comment, I can't write that query in laravel way. :-( Sorry What i wrote is sql query not laravel eloquent. :-( – Ryan Exlay Apr 19 '15 at 17:05
  • Thank zerofl4g. I solved the problem with your help. It cause two selects becoz it is subquery of preserve long query. So I can't use table name, where clasue and groupby in query. it already preserved in long query. Anyway. I can't solve without your help. thank you. :-) – Ryan Exlay Apr 19 '15 at 17:37
0

Correct query will be like

$query->where('completed', false)->get()->groupBy('subj_id');

get() will be call first before groupBy. I mean once get() make collection you can use all collection method. for more details and know all collection method https://laravel.com/docs/5.8/collections#method-groupby

polodev
  • 319
  • 2
  • 4