On Thursday, November 8, 2018 at 8:39:05 AM UTC-8, Troex Nevelin wrote:
>
> Hi, I couldn't find a way to write SELECT * INTO query, I've basically a 
> case where I need to use WITH and JOIN both when inserting into table, I'm 
> not "pro" in SQL but as far as I know the only way to implement it using is 
> SELECT INTO statement. I've been working tightly with sequel past two years 
> building complex queries but this is first time I'm really stuck.
>
> Here is full working query I'm trying rewrite into sequel
>
> WITH "visits" AS
>   (SELECT "filter",
>           COUNT("id") AS "visit_count",
>           CAST(CONVERT_TIMEZONE('America/Los_Angeles', "visit_time") AS 
> date) AS "visit_date"
>    FROM "visits_1"
>    GROUP BY "filter",
>             "visit_date")
> SELECT ("value"::float / "visit_count") AS "cpv",
>        "visit_count",
>        "visit_date",
>        "filter",
>        "value" AS "amount"
> INTO "costs_1"
> FROM "visits"
> INNER JOIN "amounts" ON (("amounts"."filter_id" = "visits"."filter")
>                          AND ("amounts"."start_date" = "visits".
> "visit_date"))
> WHERE ("project_id" = 1)
> ;
>
> And here is ruby code I currently have, which generates INSERT statement 
> which doesn't work
>
> project_id ||= 1
> timezone ||= 'America/Los_Angeles'
> visits_table = :"visits_#{project_id}"
> table_name = :"costs_#{project_id}"
>
>
> visits = DB[visits_table].
>   select(
>     :filter,
>     Sequel.lit('COUNT(?)', :id).as(:visit_count),
>     Sequel.lit('CONVERT_TIMEZONE(?, ?)', timezone, :visit_time).cast(:date
> ).as(:visit_date)
>   ).
>   group(:filter, :visit_date)
>
>
> query = DB[:visits].
>   # with(:visits, visits). # moved to insert query
>   select(
>     Sequel.lit('(?::float / ?)', :value, :visit_count).as(:cpv),
>     :visit_count,
>     :visit_date,
>     :filter,
>     Sequel.as(:value, :amount)
>   ).
>   join(:amounts, { filter_id: :filter, start_date: :visit_date }).
>   where(project_id: project_id)
>
>
> DB[table_name].
>   with(:visits, visits).
>   insert_sql(query)
>
>
> Probably the solution might be somewhere around here 
> https://github.com/jeremyevans/sequel/blob/51d96b8700df2c4cae9963bd90428efc92755e43/lib/sequel/adapters/shared/postgres.rb#L1361
>  
> I think I've seen something about SELECT INTO in MSSQL adapter code.
>
> I think my query can be rewritten without using SELECT INTO, but some 
> pieces of the ruby code are shared across my app and I'l like to keep these 
> business logic pieces "shared". Any advice or solution is welcome.
>
>
> Thank you Jeremy for best gem ever!
>

As the PostgreSQL documentation states 
(https://www.postgresql.org/docs/current/sql-selectinto.html), SELECT INTO 
is basically the same as CREATE TABLE AS, and CREATE TABLE AS is the 
recommended syntax.  Sequel supports CREATE TABLE AS via:

DB.create_table(:costs_1, :as=>DB[:visits].
  join(:amounts, :filter_id=>:filter, :start_date=>:visit_date).
  with(:visits, DB[:visits_1].
    select_group{[:filter, CONVERT_TIMEZONE('America/Los Angeles', 
:visit_time).cast(Date).as(:visit_date)]}.
    select_append{count(:id).as(:visit_count)}
  ).
  where(:project_id=>1).
  select do [
    (value.cast(Float) / visit_count).as(:cpv),
    :visit_count,
    :visit_date,
    :filter,
    value.as(:amount)
  ] end
)

Which uses the following SQL:

CREATE TABLE "costs_1" AS
WITH "visits" AS (
  SELECT "filter",
         CAST(CONVERT_TIMEZONE('America/Los Angeles', "visit_time") AS 
date) AS "visit_date",
         count("id") AS "visit_count"
  FROM "visits_1"
  GROUP BY "filter",
           CAST(CONVERT_TIMEZONE('America/Los Angeles', "visit_time") AS 
date)
)
SELECT (CAST("value" AS double precision) / "visit_count") AS "cpv",
       "visit_count",
       "visit_date",
       "filter",
       "value" AS "amount"
FROM "visits"
INNER JOIN "amounts" ON (("amounts"."filter_id" = "visits"."filter")
                         AND ("amounts"."start_date" = 
"visits"."visit_date"))
WHERE ("project_id" = 1)

Thanks,
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 sequel-talk+unsubscr...@googlegroups.com.
To post to this group, send email to sequel-talk@googlegroups.com.
Visit this group at https://groups.google.com/group/sequel-talk.
For more options, visit https://groups.google.com/d/optout.

Reply via email to