问题
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()
})
}
回答1:
##########################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)
回答2:
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'}")
来源:https://stackoverflow.com/questions/38770684/passing-a-sql-input-date-range-into-a-query-in-shiny