Red icon indicating copy to clipboard operation
Red copied to clipboard

multi-column `group by` in e.g. `.classify`

Open jonathanstowe opened this issue 4 years ago • 9 comments

I might be missing something quite obvious but it doesn't seen possible to create a group by with more than one column using .classify.

It's probably implement .reduce as per #61 as .classify doesn't seem the right place to do this.

jonathanstowe avatar Jul 31 '21 08:07 jonathanstowe

Sorry, I'm on vacation without my computer... but isn't it just a case of returning a list os columns from the classify block?

FCO avatar Jul 31 '21 23:07 FCO

I thought so too, but no it doesn't work,

Enjoy your holiday.

jonathanstowe avatar Aug 01 '21 07:08 jonathanstowe

I'm fixing it, I hadn't enough time yet today, but .classify(...).keys is already working on my implementation, now I'm fixing the rest. I hope I have some time tomorrow to play with that.

FCO avatar Sep 19 '21 03:09 FCO

@jonathanstowe could you see if something like this would solve the problem? I still have to add some tests and resolve how Bag and Set should work,

FCO avatar Sep 19 '21 20:09 FCO

I'll take a look in the morning :+1:

jonathanstowe avatar Sep 19 '21 20:09 jonathanstowe

I couldn't get it to work, do you have an example?

What I'm really trying to do is illustrated by the SQL:

select a.foo, a.bar, count(*)
from a
join b on b.a_id = a.id
group by a.foo, a.bar;

And I can't for the life of me think of a way to express it.

jonathanstowe avatar Oct 11 '21 17:10 jonathanstowe

Now it accepts multiple columns for .classify, but I don't think it will solve your issue... still working on that...

FCO avatar Dec 24 '22 01:12 FCO

@jonathanstowe I think that might be closer to what you want now (but not there yet). .classify now accepts a :&reduce (it still needs to use what-does-it-do (as the other functions)). Here is an example of usage:

➜  Red git:(master) raku -I. -MRed -e '

model Bla { has $.id is serial; has $.value is column }

my $*RED-DB = database "SQLite";
Bla.^create-table; Bla.^create(:value(<test1 test2>.pick)) xx 10;
my $*RED-DEBUG = True;

say Bla.^all.classify({ .value }, :reduce{ .elems })

'
SQL : SELECT
   DISTINCT("bla".value) as "data_1"
FROM
   "bla"
BIND: []
SQL : SELECT
   count('*') as "data_1"
FROM
   "bla"
WHERE
   "bla".value = ?
LIMIT 1
BIND: ["test1"]
SQL : SELECT
   count('*') as "data_1"
FROM
   "bla"
WHERE
   "bla".value = ?
LIMIT 1
BIND: ["test2"]
{test1 => 7, test2 => 3}

FCO avatar Dec 24 '22 04:12 FCO

Maybe we could try something like:

Model.^all.classify({ MyClassifiableClass.new: .foo, .bar }).Bag

(https://glot.io/snippets/gh56566qcg)

and create that class specifically for Red. That class could also be used to make map return objects, maybe something like:

say “a: { .a }, b: { .b }” for Model.^all.map: { MyNewClass.new: .a, .b }

FCO avatar Jan 10 '23 04:01 FCO