How to vectorize an SQL update query in R - sql

I have the following zoo object (res)
column1 column2 column3
2015-12-30 3.2735 2.3984 1.1250
2015-12-31 2.5778 1.8672 1.1371
2016-01-01 3.3573 2.4999 1.1260
2016-01-04 3.3573 2.4999 1.1463
and I would like to produce a vectorized update query.
UPDATE table SET column1=3.2735, column2=2.3984, column3=1.1250 WHERE dt = '2015-12-30';
UPDATE table SET column1=2.5778, column2=1.8672, column3=1.1371 WHERE dt = '2015-12-31';
etc.
I was able to do something similar previously for an INSERT query
sColumns <- paste0("dt, index, ", paste0(colnames(res), collapse=", "))
sValues = apply(data.frame(paste0("'", index(res), "'"), paste0("'", index, "'"), coredata(res)),
1 , paste, collapse = ",")
sql <- paste0("INSERT INTO table (", sColumns, ") VALUES (", sValues, ")")
which was considerably easier because all column names were grouped, and all values were grouped. For an UPDATE query, I have to combine alternately columns and fields.
So far, I have the following:
sColumns <- paste0(colnames(res), "=")
tmp <- paste(c(matrix(c(sColumns, res[1, ]), 2, byrow = T)), collapse = ", ")
tmp <- gsub("=, ", "=", tmp)
Which produces (for one row), output like:
[1] "column1=3.2735, column2=2.3984, column3=1.125"
Can anyone provide guidance as to how I can use something like apply() to do this for all rows of 'res'?

1) Try this:
library(zoo)
sapply(1:nrow(res), function(i) paste0(
"UPDATE table SET ",
toString(paste0(names(res), "=", coredata(res)[i, ])),
" WHERE dt='", time(res)[i], "'"))
giving the following character vector:
[1] "UPDATE table SET column1=3.2735, column2=2.3984, column3=1.125 WHERE dt='2015-12-30'"
[2] "UPDATE table SET column1=2.5778, column2=1.8672, column3=1.1371 WHERE dt='2015-12-31'"
[3] "UPDATE table SET column1=3.3573, column2=2.4999, column3=1.126 WHERE dt='2016-01-01'"
[4] "UPDATE table SET column1=3.3573, column2=2.4999, column3=1.1463 WHERE dt='2016-01-04'"
2) And a variation giving the same result:
sapply(unname(split(res, time(res))), function(z) paste0(
"UPDATE table SET ",
toString(paste0(names(z), "=", z)),
" WHERE dt='", time(z), "'"))
Note 1: If your table is not too large then you could alternately consider reading it into R, performing the update in R and then writing it back.
Note 2: Here is the input shown reproducibly:
Lines <- "Date column1 column2 column3
2015-12-30 3.2735 2.3984 1.1250
2015-12-31 2.5778 1.8672 1.1371
2016-01-01 3.3573 2.4999 1.1260
2016-01-04 3.3573 2.4999 1.1463"
library(zoo)
res <- read.zoo(text = Lines, header = TRUE)

Is this what you want?
foo <- apply(res,1, function(x){
sprintf("%s = %f", names(x),x)
})
lapply(colnames(foo), function(nn) {
sprintf("UPDATE table SET %s WHERE dt = \'%s\'",
paste(foo[,nn], collapse=","),
nn)
})
which gives:
[[1]]
[1] "UPDATE table SET column1 = 3.273500,column2 = 2.398400,column3 = 1.125000 WHERE dt = '2015-12-30'"
[[2]]
[1] "UPDATE table SET column1 = 2.577800,column2 = 1.867200,column3 = 1.137100 WHERE dt = '2015-12-31'"
[[3]]
[1] "UPDATE table SET column1 = 3.357300,column2 = 2.499900,column3 = 1.126000 WHERE dt = '2016-01-01'"
[[4]]
[1] "UPDATE table SET column1 = 3.357300,column2 = 2.499900,column3 = 1.146300 WHERE dt = '2016-01-04'"

Related

how to display columns in specific order, according to field value in MS Access

I want to display a query but the column order needs to be sorted according to the value in the column, field with greater value as column 1, then second greater value field as column 2, and so on. The query will only produce one row as it shows data for the current month. I know I could do this in VBA, with a bubble sort or something, and build the SQL query accordingly, but I was wondering if there was a quicker way to do this. Data is like this: DataMonth, Data1, Data2, Data3,... all the way to Data8. Please don't mention data structure is bad, as I am only trying to help someone here, and it is a bit too late to rebuild their tables structures...
No need to sort in the VBA. First get a record set that lists the columns in the right order with the Column Name as one of the columns - order that query by the value in each column. I used a query that got each single column with UNION e.g. here is my entire module
Option Compare Database
Option Explicit
Private Sub ReorderColumns()
Dim mnth As Integer
mnth = 1 'CHANGE MONTH
Dim qry As String
Dim rs As DAO.Recordset
qry = GetSQL(mnth)
Set rs = CurrentDb.OpenRecordset(qry)
Dim i As Integer: i = 0 'Count of columns added to query
qry = "SELECT "
While Not rs.EOF
i = i + 1
qry = qry & rs.Fields("ColName") & IIf(i < 8, ",", "")
rs.MoveNext
Wend
qry = qry & " FROM Table1 WHERE DataMonth = %s"
qry = stuffStr(qry, mnth)
rs.Close
'Get the results in the order you need
Set rs = CurrentDb.OpenRecordset(qry)
'Do something with the data here
rs.Close
Set rs = Nothing
End Sub
Public Function GetSQL(mnth As Integer) As String
Dim outp As String
outp = "SELECT 'Data1' as ColName, Data1 as DataValue FROM Table1 WHERE DataMonth = %s UNION ALL " & _
"SELECT 'Data2' as ColName, Data2 as DataValue FROM Table1 WHERE DataMonth = %s UNION ALL " & _
"SELECT 'Data3' as ColName, Data3 as DataValue FROM Table1 WHERE DataMonth = %s UNION ALL " & _
"SELECT 'Data4' as ColName, Data4 as DataValue FROM Table1 WHERE DataMonth = %s UNION ALL " & _
"SELECT 'Data5' as ColName, Data5 as DataValue FROM Table1 WHERE DataMonth = %s UNION ALL " & _
"SELECT 'Data6' as ColName, Data6 as DataValue FROM Table1 WHERE DataMonth = %s UNION ALL " & _
"SELECT 'Data7' as ColName, Data7 as DataValue FROM Table1 WHERE DataMonth = %s UNION ALL " & _
"SELECT 'Data8' as ColName, Data8 as DataValue FROM Table1 WHERE DataMonth = %s ORDER BY 2"
GetSQL = stuffStr(outp, mnth, mnth, mnth, mnth, mnth, mnth, mnth, mnth)
End Function
Function stuffStr(str As String, ParamArray subs()) As String
Dim i As Long
Dim outp As String
outp = str
For i = 0 To UBound(subs)
outp = Replace(Expression:=outp, Find:="%s", Replace:=subs(i), Count:=1, Compare:=vbTextCompare)
Next
stuffStr = outp
End Function
Not the most efficient way because of all the string manipulation, but it works

Filtering with sqldf in R when fields have quotation marks

I have a large sql db (7gbs), where the fields appear to have quotation marks in them.
For example:
res <- dbSendQuery(con, "
SELECT *
FROM master")
dbf2 <- fetch(res, n = 3)
dbClearResult(res)
Yields
NPI EntityTypeCode ReplacementNPI EmployerIdentificationNumber.EIN.
1 "1679576722" "1" "" ""
2 "1588667638" "1" "" ""
3 "1497758544" "2" "" "<UNAVAIL>"
ProviderOrganizationName.LegalBusinessName. ProviderLastName.LegalName. ProviderFirstName
1 "" "WIEBE" "DAVID"
2 "" "PILCHER" "WILLIAM"
3 "CUMBERLAND COUNTY HOSPITAL SYSTEM, INC" "" ""
I've been trying to get a smaller table by filtering on, say EntityTypeCode but I'm not getting any results. Here's an example of a query not getting anything, any advice? I think the issue is use of double quotes in the fields.
# Filter on State
res <- dbSendQuery(npi2, "
SELECT *
FROM master
WHERE (ProviderBusinessPracticeLocationAddressStateName = 'PA')
")
# Filter on State and type
res <- dbSendQuery(npi2, "
SELECT *
FROM master
WHERE (ProviderBusinessPracticeLocationAddressStateName = 'PA') AND
(EntityTypeCode = '1')
")
Escape the inner double quotes (ie, the ones in the cell) with a \.
res <- dbSendQuery(npi2, "
SELECT *
FROM master
WHERE (ProviderBusinessPracticeLocationAddressStateName = '\"PA\"') AND
(EntityTypeCode = '1')
")
This produces the following string:
SELECT *
FROM master
WHERE (ProviderBusinessPracticeLocationAddressStateName = '"PA"')

Concatenating key value pairs from a list in R

I have a list of objects that I would like to concatenate into a string. This will ultimately be used to construct a SQL statement.
library(purrr)
test <- list(key = "value", key1 = "value1", key2 = "value2")
> test
$key
[1] "value"
$key1
[1] "value1"
$key2
[1] "value2"
map2(names(test), test, ~paste(.x, "=", .y)) %>%
reduce(c) %>%
paste0(collapse = ", ")
This gives the desired result, but wondering if I'm missing a more obvious solution.
[1] "key = value, key1 = value1, key2 = value2"
You can use paste
You can obtain the same result by only using paste:
paste(names(test), test, sep = " = ", collapse = ", ")
Output:
[1] "key = value, key1 = value1, key2 = value2"
Hope this helps.
Or we can convert to a data.frame and paste with do.call
do.call(paste, c(stack(test)[2:1], sep=" = ", collapse=", "))
#[1] "key = value, key1 = value1, key2 = value2"

Access VBA error in inserting long text into table

In Access I have 2 tables, table_A and table_B. In col2 from table_A, I have an R function as cell value.
mdPatternChart<-function (x, Str_PathFile)
{
if (!(is.matrix(x) || is.data.frame(x)))
stop("Data should be a matrix or dataframe")
if (ncol(x) < 2)
stop("Data should have at least two columns")
R <- is.na(x)
nmis <- colSums(R)
R <- matrix(R[, order(nmis)], dim(x))
pat <- apply(R, 1, function(x) paste(as.numeric(x), collapse = ""))
sortR <- matrix(R[order(pat), ], dim(x))
if (nrow(x) == 1) {
mpat <- is.na(x)
} else {
mpat <- sortR[!duplicated(sortR), ]
}
if (all(!is.na(x))) { cat(" /\\ /\\\n{ `---' }\n{ O O }\n==> V <==")
cat(" No need for mice. This data set is completely observed.\n")
cat(" \\ \\|/ /\n `-----'\n\n")
mpat <- t(as.matrix(mpat, byrow = TRUE))
rownames(mpat) <- table(pat)
} else {
if (is.null(dim(mpat))) {
mpat <- t(as.matrix(mpat))
}
rownames(mpat) <- table(pat)
}
r <- cbind(abs(mpat - 1), rowSums(mpat))
r <- rbind(r, c(nmis[order(nmis)], sum(nmis)))
png(file=paste(Str_PathFile,".png",sep=""),bg="transparent")
plot.new()
if (is.null(dim(sortR[!duplicated(sortR), ]))) {
R <- t(as.matrix(r[1:nrow(r) - 1, 1:ncol(r) - 1]))
} else {
if (is.null(dim(R))) {
R <- t(as.matrix(R))
}
R <- r[1:nrow(r) - 1, 1:ncol(r) - 1]
}
par(mar = rep(0, 4))
plot.window(xlim = c(-1, ncol(R) + 1), ylim = c(-1, nrow(R) +
1), asp = 1)
M <- cbind(c(row(R)), c(col(R))) - 1
shade <- ifelse(R[nrow(R):1, ], mdc(1), mdc(2))
rect(M[, 2], M[, 1], M[, 2] + 1, M[, 1] + 1, col = shade)
adj = c(0, 0.5)
srt = 90
for (i in 1:ncol(R)) {
text(i - 0.5, nrow(R) + 0.3, colnames(r)[i], adj = adj,
srt = srt)
text(i - 0.5, -0.3, nmis[order(nmis)][i])
}
for (i in 1:nrow(R)) {
text(ncol(R) + 0.3, i - 0.5, r[(nrow(r) - 1):1, ncol(r)][i],
adj = 0)
text(-0.3, i - 0.5, rownames(r)[(nrow(r) - 1):1][i],
adj = 1)
}
text(ncol(R) + 0.3, -0.3, r[nrow(r), ncol(r)])
dev.off()
}
Now I would like to insert this into col2 of table_B. Col2 from both tables are memo. It works as
CurrentDb.Execute "insert into Table_B (Col1,Col2) select Col1,Col2 from Table_A"
But it does not work if I use DAO.recordset as below.
CurrentDb.Execute "insert into Table_B (Co1,Col2) values (2,'" & Rs_TableA.Fields("Col2") & "')"
And it gave a run-time error 3075 saying something is wrong with the syntax. I replaced ! and " in the function but it did not work. I also tried by saving its value in a string variable before inserting and it did not work either. As I need to loop through table_A, Can anyone help? Thanks!
The function text contains apostrophes and quote characters. These characters have special meaning in SQL statements. The SELECT subquery won't have an issue but the constructed SQL pulling value from recordset is trying to process them as special characters, not as just simple text. This causes the compiled statement to be nonsense to the SQL engine. Review How do I escape a single quote in SQL Server?.
Options for handling:
Replace(Replace([fieldname], "'", "''"), Chr(34), Chr(34) & Chr(34))
Open a source recordset and a target recordset, loop through source and use AddNew and Update to write records to target
Maybe the SELECT subquery version will actually serve requirement, and if the ID should be supplied dynamically by textbox:
CurrentDb.Execute "INSERT INTO Table_B (Col1,Col2) SELECT " & Me.tbxID & " As C1, Col2 FROM Table_A"
Also, there are 2 slanted apostrophes where I think there should be normal apostrophes.

Query SQL update column image

I'm testing the following query to update the columns in a SQL Server database, reporting the following code:
data1 = textbox
data2 = TextBox2
using ms as new MemoryStream ()
DirectCast (picturebox1.image, botmap) .save (ms currentFormat)
image = ms.toArray ()
end using
Dim param as SqlParameter () = _
new SqlParameter () {new SqlParameter ("# data1", _
data1), new SqlParameter ("# data2", data2), new SqlParameter ("# image", image)}
mcmd.commandText = "update set table column1 = '" + data1 + "', column2 '" + data1 + "'"
mcmd.parameters.add ("# image", SqlDbType.varbinary, 8000) .Value = image
The line of code only updates the values ​​data1 and data2 but the image is not updated
How can I fix this?
Look at your UPDATE statement below; it doesn't looks correct at all syntactically, and you are missing = after column2
mcmd.commandText = "update set table column1 = '" + data1 + "', column2 '" + data1 + "'"
It should be
mcmd.commandText = "update table_name set column1 = '" + data1 + "', column2 = '" + data2 + "'"
Also, you have already declared parameters for the values, so use them in your UPDATE statement
mcmd.commandText = "update table_name set column1 = #data1, column2 = #data2