On Thursday, November 5, 2015 at 5:25:24 PM UTC-3, Jeremy Evans wrote:
>
> On Thursday, November 5, 2015 at 12:14:32 PM UTC-8, flyer wrote:
>>
>> Hi, I am struggling a lot trying to translate this query into Sequel DSL.
>> Suppose I have the following table schemas (only showing meaningful
>> columns):
>>
>> Table "public.products"
>> Column | Type |
>> Modifiers
>>
>> ---------------------+-----------------------------+-------------------------------------------------------
>> id | integer | not null default
>> nextval('products_id_seq'::regclass)
>> name | character varying(45)
>> product_category_id | integer |
>>
>>
>> Table "public.product_categories"
>> Column | Type |
>> Modifiers
>>
>> -----------------------+------------------------+-----------------------------------------------------------------
>> id | integer | not null default
>> nextval('product_categories_id_seq'::regclass)
>> name | character varying(255)
>> parent_id | integer |
>>
>> So products can have categories, and categories can have subcategories.
>> Moreover products may belong to a parent category and not necessarily to
>> subcategories. So suppose I have the following categories and products data:
>>
>> Categories Table
>>
>> id name parent_id
>> 1 Drinks
>> 2 Starters
>> 3 Alcohol 1
>> 4 Without Alcohol 1
>> 5 Cold 2
>> 6 Hot 2
>>
>> Products Table
>>
>>
>> id name product_category_id
>> 1 Coca-Cola 4
>> 2 Water 4
>> 3 Wine 3
>> 4 Beer 3
>> 5 Orange Juice 1
>> 6 Picada Chica 2
>> 7 Muzz Milanesa 6
>> 8 Salpicon Ave 5
>>
>> So notice that some products just belong to "main_categories". What I
>> want to do is return a set ordered alphabetically first by "main_category",
>> then by "subcategory" and finally by product name. I was able to do this in
>> plain SQL executing the following query:
>>
>> SELECT p.name, p.id, p.product_category_id, ij.main_category, ij.subcategory
>> FROM
>> products p inner join
>> (select pc.id, coalesce(pcc.name, pc.name) main_category, case when pcc
>> .name is not null THEN pc.name end subcategory FROM product_categories
>> pc left join product_categories pcc on pc.parent_id = pcc.id) ij on
>> p.product_category_id
>> = ij.id order by ij.main_category, ij.subcategory nulls first, p.name;
>>
>
> Assuming you are using models, I think this will work:
>
> Product.many_to_one :category
> Category.many_to_one :parent
>
> Product.association_left_join(:category=>:parent).
> exclude(:category__id=>nil).
> select(:product__name, :product__id, :product__product_category_id,
> :parent__name___main_category, :category__name___subcategory).
> order(:parent__name___main_category, :category__name___subcategory,
> :product__name)
>
> It works differently from your query, as it doesn't join to a subquery.
> Not sure which performs better, you'd have to benchmark. If you want a
> more direct translation of the subquery approach that doesn't use model
> associations, please let me know.
>
> Thanks,
> Jeremy
>
Thanks for your reply Jeremy. Yes I am using Sequel models. In your query,
when you qualify the products table, instead of :product shouldnt it be
:producs?
Unfortunately your aproarch did not work. I mean, it worked, but not with
the expected order. I think the main problem there is with null
"main_category" values. And those are the products that do not belong to
any subcategories. Or is the same to say: products that belong to
"main_categories". So for example, with a local test I obtained the
following result executing the query:
name | id | product_category_id |
main_category | subcategory
----------------------------------------+----+---------------------+---------------+--------------------
Agua Mineral 200 cm3 edit2 | 9 | 11 | Bebidas
| Sin alcohol
Agua Mineral Gasificada | 50 | 11 | Bebidas
| Sin alcohol
Coca-Cola 375 cm3 | 1 | 11 | Bebidas
| Sin alcohol
Tinto | 21 | 9 | Bebidas
| Vinos
Medialunas | 8 | 30 | Cafeter
ía | Medialunas
Muzzarella a la Milanesa | 44 | 20 |
Entradas | Calientes
Revuelto de Gramajo | 47 | 20 |
Entradas | Calientes
Tortilla de Papas | 52 | 20 |
Entradas | Calientes
Salpicon de Ave | 49 | 19 |
Entradas | Frias
Vitel Tone | 45 | 19 |
Entradas | Frias
Aquarius | 36 | 1 |
| Bebidas
Coca Zero | 54 | 1 |
| Bebidas
Crush | 34 | 1 |
| Bebidas
Paso de los Toros | 35 | 1 |
| Bebidas
Pesi | 46 | 1 |
| Bebidas
Sprite 375 cm3 | 23 | 1 |
| Bebidas
Cafe Chico | 6 | 2 |
| Cafetería
Cafe Jarrito | 7 | 2 |
| Cafetería
Capuccino | 18 | 2 |
| Cafetería
Submarino | 24 | 2 |
| Cafetería
Picada Chica | 53 | 13 |
| Entradas
<> años ü árbol | 14 | 3 |
| Platos Principales
Berenjenas en Escabeche | 19 | 3 |
| Platos Principales
Bife de Kobe | 22 | 3 |
| Platos Principales
Milanesa Napolitana | 11 | 3 |
| Platos Principales
Papas Fritas | 12 | 3 |
| Platos Principales
Pizza elab | 17 | 3 |
| Platos Principales
Pizza Muzarella | 2 | 3 |
| Platos Principales
Producto largo y Probl3m@tica. <>ü; <> | 13 | 3 |
| Platos Principales
bombon suiz | 15 | 4 |
| Postres
Brownie | 27 | 4 |
| Postres
Cheessecake | 26 | 4 |
| Postres
Ensalada de Frutas | 10 | 4 |
| Postres
Panqueue Dulce de Leche | 20 | 4 |
| Postres
As you can see, the order is partially correct. The columns also are not
representing the correct category level, for example Aquarius belong to
main category "Bebidas", but has none subcategory.
I was able to migrate the query to DSL. I am not happy with the result, but
it worked. Is there any improvement I can make?
subcategories_dataset = ProductCategory
.left_join(:product_categories___pcc, id: :parent_id)
.select(:product_categories__id,
Sequel.function(:coalesce, :pcc__name, :product_categories__name).
as(:main_category),
Sequel.case([[Sequel.lit('pcc.name is not null'), :
product_categories__name]], nil).as(:subcategory))
Product
.exclude(product_type_id: 3)
.inner_join(subcategories_dataset, id: :product_category_id)
.select_all(:products)
.select_append(:t1__main_category, :t1__subcategory)
.eager({ proportions: :ingredient }, { product_category: :parent }, :
provider)
.order(:t1__main_category, Sequel.asc(:t1__subcategory, nulls: :first), :
products__name)
I am eagerly loading other models I need, but the really important thing I
need, is to return the products in the corrrect order, then is trivial.
Thanks a lot for your support Jeremy.
--
You received this message because you are subscribed to the Google Groups
"sequel-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/sequel-talk.
For more options, visit https://groups.google.com/d/optout.