1

I'm learning to use Shiny and shiny dashboard and working with a sql database SQL-SERVER where I'd like to pull the data straight from the database. Essentially the idea is to merge to columns in a table that have a start spot and a stop spot for a date range, tabulate them and then diagram them.

I found the following posting on how to pass sql input statements into shiny: How to pass input variable to SQL statement in R shiny?

Unfortunately when I try and apply this I get an error 'subscript is out of bounds; it looks like the query isn't being pulled in. I've tested it separately and was able to pull the data and run through each step without issue. I am using the RODBC package which I wonder if this is the issue. Below is my code:

         library(stringr)
        library(RODBC)
          library(circlize)
         library(shinydashboard)
         library(shiny)

                ui <- dashboardPage(skin = "blue",
                dashboardHeader(title = "sample"),
                dashboardSidebar(disable = TRUE),
                dashboardBody(
                  # Boxes need to be put in a row (or column)
                  fluidRow(
                    box(title = "Route Volume", background = "green", solidHeader = TRUE,
                        plotOutput(outputId= 'plot2'))),
                    fluidRow( 
                      box(background= "green", dateRangeInput("dates", label = h3("Date Range"),start = '2016-06-01',
                                                              end = '2016-06-05')), width = 4

                      ))))

              server <- function(input, output) {
            database = odbcConnect("datatbase")
            output$plot2 = renderPlot({

            d = paste0("SELECT 
               top 30
           convert(char(10),datetime,121) as date, 
           cast(start_destination as varchar(3)) 
           + (',') + cast(final_destination as varchar(3)) as combo,
           count(cast(start_destination as varchar(3)) 
           + (',') + cast(final_destination as varchar(3))) as volume
           FROM
           trips
           WHERE datetime >= ",input$dates[1]," AND
           datetime < ",input$dates[2],"
           GROUP BY
           cast(start_destination as varchar(3)) 
           + (',') + cast(final_destination as varchar(3)),
           convert(char(10),datetime,121);")

        sql = sqlQuery(database, d)

           sql = data.frame(sql, do.call(rbind, str_split(sql$combo, ',')))
       colnames(sql)[colnames(sql)=="X1"] <- "From"
         colnames(sql)[colnames(sql)=="X2"] <- "To"
         sql = sql[,c(4,5,3)]
         sql = sql[order(sql$volume, decreasing = T),]
          chordDiagram(sql)
          circos.clear()

          })

          }


          shinyApp(ui, server)

I'm sure this is some silly mistake, a missing quotation mark or a misunderstanding on my part of how to apply these techniques. Appreciate the help!!

                ##adding edits by Dean to test



              database = odbcConnect("database")
             output$plot2 = renderPlot({
              if(input$dates[1]!= "") {
               d = paste0("SELECT 
            top 30
          convert(char(10),datetime,121) as date, 
          cast(start_destination as varchar(3)) 
          + (',') + cast(final_destination as varchar(3)) as combo,
          count(cast(start_destination as varchar(3)) 
          + (',') + cast(final_destination as varchar(3))) as volume
          FROM
           trips
           WHERE 
           datetime >= ",input$dates[1]," AND
           datetime < ",input$dates[2],"
           GROUP BY
          cast(start_destination as varchar(3)) 
          + (',') + cast(final_destination as varchar(3)),
           convert(char(10),datetime,121);")
         sql = sqlQuery(database, d) 

        #i assumed the if statement ended here so I put the 
        #bracket below 
           sql = data.frame(sql, do.call(rbind, str_split(sql$combo, ',')))
       colnames(sql)[colnames(sql)=="X1"] <- "From"
         colnames(sql)[colnames(sql)=="X2"] <- "To"
         sql = sql[,c(4,5,3)]
         sql = sql[order(sql$volume, decreasing = T),]
          chordDiagram(sql)
          circos.clear() 

}
    })

   }

Putting up edits to the server following suggestions by NJburgo ##################################NJburgo suggestion################ #I get the error: Do not know how to convert input$dates to class date

                       database = odbcConnect("database")
                           output$plot2 = renderPlot({
                           dates = as.Date(input$dates)
                           d = paste0("SELECT 
                       top 30
                      convert(char(10),datetime,121) as date, 
                     cast(start_destination as varchar(3)) 
                      + (',') + cast(final_destination as varchar(3)) as combo,
                       count(cast(start_destination as varchar(3)) 
                     + (',') + cast(final_destination as varchar(3))) as volume  
                     FROM
                    trips
                      WHERE 
                      datetime >= {d '",input$dates[1],"'} AND
                       datetime < {d '",input$dates[2],"'}
                        GROUP BY
                      cast(start_destination as varchar(3)) 
                       + (',') + cast(final_destination as varchar(3)),
                        convert(char(10),datetime,121);")
                   sql = sqlQuery(database, d) 


                   sql = data.frame(sql, do.call(rbind, str_split(sql$combo, ',')))
                 colnames(sql)[colnames(sql)=="X1"] <- "From"
                 colnames(sql)[colnames(sql)=="X2"] <- "To"
                 sql = sql[,c(4,5,3)]
                 sql = sql[order(sql$volume, decreasing = T),]
               chordDiagram(sql)
                   circos.clear() 

               })

             }
11
  • 2
    Using string concatenation to construct a SQL query is a bug in itself. Unexpected conversions of date and number parameters are just one of the problems that it can cause. Use proper parameterized queries to avoid all quoting, format and security issues Commented Aug 4, 2016 at 15:12
  • One guess is that shiny is running the sql before the input$dates has values in it. I would put print(input$dates[1]) and print(input$dates[2]) before the sql query happens and then run the app. This assumes you're running from Rstudio so that you can see what it prints in the Rstudio window. Commented Aug 4, 2016 at 15:36
  • Hey Dean. I tried printing the input$dates but it made no difference. Im sure the issue is here because when dates are hardcoded the data pulls without issue. Commented Aug 4, 2016 at 16:10
  • I didn't expect the printing to make a difference. It's just a debugging step. Did it print the dates or did it print blanks? Commented Aug 4, 2016 at 16:18
  • Gotcha. It didn't print anything. Just blanks, it's as if shiny isn't interpreting input$dates to put into the SQL query which is why the query is blank too Commented Aug 4, 2016 at 16:35

2 Answers 2

0
##########################figured out answer. It required a combination of both suggestions from all of you making sure date printed and was converted as well. Thank you all!Below is working code
                server <- function(input, output) {

             output$plot2 = renderPlot({
           database = odbcConnect("database")
              start_date = print(input$dates[1])
              end_date = print(input$dates[2])
              my_query="SELECT 
              top 30
                        convert(char(10),datetime,121) as date, 
                         cast(start_destination as varchar(3)) 
                        + (',') + cast(final_destination as varchar(3)) as combo,
                           count(cast(start_destination as varchar(3)) 
                           + (',') + cast(final_destination as varchar(3))) as volume  
                          FROM
                          trips
                              WHERE 
                           datetime >= DATE1 AND
                           datetime < DATE2
                            GROUP BY
                             cast(start_destination as varchar(3)) 
                           + (',') + cast(final_destination as varchar(3)),
                             convert(char(10),datetime,121);"

                my_query <- sub("DATE1",as.Date(start_date),my_query);
              my_query <- sub("DATE2",as.Date(end_date),my_query)
             sql = sqlQuery(database, paste(my_query))
            sql = data.frame(sql, do.call(rbind, str_split(sql$combo, ',')))
           colnames(sql)[colnames(sql)=="X1"] <- "From"
           colnames(sql)[colnames(sql)=="X2"] <- "To"
           sql = sql[,c(4,5,3)]
            sql = sql[order(sql$volume, decreasing = T),]
            chordDiagram(sql)
             circos.clear()
               })


             }


             shinyApp(ui, server)
Sign up to request clarification or add additional context in comments.

Comments

-1

I don't think this as R thing, more likely SQL, especially if your query works with ordinary dates outside of Shiny (hint: test this, report back!).

For date comparison in SQL have always had to convert the date as so:

...WHERE col_name >= {d '2016-08-04'}...

So you have to format the date in R. The simplest way to do this is with format:

format(Sys.Date(), "{d '%Y-%m-%d'}")

5 Comments

You don't have to convert dates if you avoid string concatenation and use parameterized queries. If you have to use them, the unambiguous date format is the unseparated format, ie 20160804. In any case, it's far easier and safer to use RODBCext which supports parameterized queries
thanks for the tips guys. Panagiotos, I think parameterized queries are definitely where I will need to move after this, but I'm not sure that's the issue here. The query runs fine as is outside of shiny, it just stops inside of shiny. I went ahead and tried your solution NJBurgo pulling with this: WHERE col_name >= {d '",input$dates[1],"'} so that the data is converted to date format and still had not success (this did work outside of shiny though). I did notice that when I hard code dates into the query works fine. So I think the issue is with input$dates. not sure where. Any ideas?
@LoF10, in shiny the input from a selectDate is a string, and needs to be converted. Use date <- as.Date(input$date) to get a date conversion. Then you can format either using the solution I posted, or formatting it like @panagiotis-kanavos suggested format(date, '%Y%m%d').
Hey NJburgo, thanks for the update, so I went ahead and gave it a shot. Didn't work but it might be the way I set it up. I added the edits to the post above if you could take a quick look. I wasn't sure if I was supposed to convert both dates[1] and dates[2] or just 'dates'. Either way I got the error "Do not know how to convert input$dates to class Date".
I did also try dates = format(input$dates, '%Y%m%d') which got me the error: Error in $: $ operator is invalid for atomic vectors

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.