2013-01-01 13 views
5
Używanie

Przy użyciu Chciałbym dołączyć dwa podzapytania, które dzielą niektóre nazwy kolumn, a następnie tabelę - kwalifikują się te kolumny w select.Sequel - czy mogę aliasować podzapytania w złączeniu?

rozumiem, jak to zrobić, jeśli dwa zestawy danych są tylko tabele. Na przykład. jeśli mam users tabelę i tabelę items z przedmiotów należących do użytkowników, a ja chcę do listy nazw i ich właścicieli elementy nazwy:

@db[:items].join(:users, :id => :user_id). 
    select{[items__name, users__name.as(user_name)]} 

produkuje

SELECT "items"."name", "users"."name" AS "user_name" 
    FROM "items" 
INNER JOIN "users" ON ("users"."id" = "items"."user_id") 

jako pożądane.

Jednak jestem pewien jak to zrobić, jeśli mam połączenie dwóch dowolnych zestawów danych reprezentujących podzapytania (nazywamy je my_items i my_users)

Składnia przypuszczalnie przyjąć formę

my_items.join(my_users, :id => :user_id). 
    select{[ ... , ... ]} 

gdzie Podam kwalifikowane nazwy kolumn, aby uzyskać dostęp do my_users.name i my_items.name. Jaka jest odpowiednia składnia, aby to zrobić?

Częściowym rozwiązaniem jest użycie t1__name do pierwszego argumentu, ponieważ wydaje się, że zbiór danych dostarczane do złączenia jest aliasem z t1, t2 itp Ale to nie pomaga mi zakwalifikować nazwę elementu, który muszę dostarczyć drugi argument.

Myślę, że najbardziej pożądane rozwiązanie umożliwiłoby podanie aliasów dla zestawów danych w łączeniu, np. jak poniżej (choć oczywiście to nie działa dla wielu powodów)

my_items.as(alias1).join(my_users.as(alias2), :id => :user_id). 
    select{[alias1__name, alias2__name ]} 

Czy istnieje jakiś sposób, aby to zrobić?

Dzięki!

Aktualizacja

myślę from_self robi mi część drogi tam, na przykład

my_items.from_self(:alias => :alias1).join(my_users, :id => :user_id). 
    select{[alias1__name, t1__name]} 

wydaje się postępować właściwie.

Odpowiedz

5

OK, dzięki za podpowiedź Ronalda Holshausen, dostał.Kluczem jest wykorzystanie .from_self pierwszego zestawu danych i zapewniają opcję w sprzężeniu :table_alias:

my_items.from_self(:alias => :alias1). 
    join(my_users, {:id => :user_id}, :table_alias => :alias2). 
    select(:alias1__name, :alias2__name) 

daje SQL

 SELECT "alias1"."name", "alias2"."name" 
     FROM (<my_items dataset>) AS "alias1" 
    INNER JOIN (<my_users dataset>) AS "alias2" 
      ON ("alias2"."id" = "alias1"."user_id") 

Zauważ, że dołączyć hash (drugi argument join) potrzeb jawne nawiasy klamrowe w celu odróżnienia go od hasha opcji, które obejmuje :table_alias.

1

Jedynym sposobem znalazłem użyć metody from na DB, a :table_alias na metodzie join, ale te nie działają z modeli, więc musiałem użyć table_name z klasy modelu. Tj

1.9.3p125 :018 > @db.from(Dw::Models::Contract.table_name => 'C1') 
=> #<Sequel::SQLite::Dataset: "SELECT * FROM `vDimContract` AS 'C1'"> 
1.9.3p125 :019 > @db.from(Dw::Models::Contract.table_name => 'C1').join(Dw::Models::Contract.table_name, {:c1__id => :c2__id}, :table_alias => 'C2') 
=> #<Sequel::SQLite::Dataset: "SELECT * FROM `vDimContract` AS 'C1' INNER JOIN `vDimContract` AS 'C2' ON (`C1`.`Id` = `C2`.`Id`)"> 
1.9.3p125 :020 > @db.from(Dw::Models::Contract.table_name => 'C1').join(Dw::Models::Product.table_name, {:product_id => :c1__product_id}, :table_alias => 'P1') 
=> #<Sequel::SQLite::Dataset: "SELECT * FROM `vDimContract` AS 'C1' INNER JOIN `vDimProduct` AS 'P1' ON (`P1`.`ProductId` = `C1`.`ProductId`)"> 

Jedyne co mi się nie podoba from_self jest używa podzapytania:

1.9.3p125 :021 > Dw::Models::Contract.from_self(:alias => 'C1') 
=> #<Sequel::SQLite::Dataset: "SELECT * FROM (SELECT * FROM `vDimContract`) AS 'C1'"> 
+0

Oh! To jest to, czego potrzebuję. Nie ma problemu z podzapytaniem, chociaż zgadzam się, że to nieprzyjemne. – brahn