Conversion of Foxpro code to Set-Based MySQL Query - mysql

Trying to convert a Visual Foxpro code to set-based MySQL query. Following is the code segment from Foxpro
lnFound=0
IF LnFound = 0 .and. rcResult = "ALL" AND PcOpOrIp = "OP"
SELECT PFile
LcTag = ORDER()
SET ORDER TO TAG PtcntlNm
=SEEK(LcPatientNo)
SCAN WHILE PtcntlNm = LcPatientNo
IF GcMResult <= "0"
GcMResult = "1-7MAT-PTC"
ENDIF
IF MONTH(cSRa.Fromdate) = MONTH(pFile.Fromdate) ;
.AND. pFile.ThruDate >= cSRa.ThruDate
** Check From/Thru Date against pFile
IF (ABS(cSRa.totalchrg) = (pFile.BDeduct+pFile.Deduct+pFile.Coinsur)) .OR. cSRa.Tchrgs = (pFile.BDeduct+pFile.Deduct+pFile.Coinsur) .or. (ABS(cSRa.totalchrg) = pFile.Total .OR. cSRa.Tchrgs = pFile.Total)
IF lnFound = 0
gcRecid = recid
gcmResult=rcResult
ENDIF
lnFound = lnFound + 1
gcUNrECID = gcunRecid + IIF(EMPTY(gCUNreCID),Recid,[,]+recid)
ENDIF
ENDIF
ENDSCAN
SELECT PFile
SET ORDER TO &LcTag
ENDIF
I have a table named pfile which I'am trying to join with another table named csra. The main aim of this is to set the record_id (gcrecid) based on the condition of three nested if statements. After setting the gcrecid variable the lnfound variable is set to one hence the third if statement condition is false from the second iteration onwards.
Here is the MySQL stored procedure which I came up with and as you can see I'm not able to completely convert the code in an efficient manner.
UPDATE csra AS cs
JOIN p051331s AS p ON cs.patientno = p.ptcntlnm
SET cs.recid = p.recid
, cs.mcsult = "ALL"
, cs.lnfound = '"1"'
WHERE cs.provider = '051331'
AND cs.lnfound = "0"
AND cs.RECID IS NULL
AND month(cs.fromdate) = month(p.fromdate)
AND p.thrudate >= cs.ThruDate
AND ABS(cs.totalchrg) = (p.bdeduct+p.deduct+p.coinsur)
OR cs.tchrgs = (p.bdeduct+p.deduct+p.coinsur)
OR ABS(cs.totalchrg) = p.total OR cs.tchrgs = p.total;
Any lead in this regard will be much appreciated as I've been working on this procedure for a couple of day with no noticeable results.

According to this partial VFP code (which is not clear on variables it uses) there is no code to be converted to set based at all. Corresponding mySQL or MS SQL or any other SQL series backend code would simply be "nothing". ie: this would be equivalant:
-- Hello to mySQL or MS SQL
PS: On your trial to convert to an update code, inner joining with csra is wrong. It is not joined in VFP code, csra values are constant --unless there is a relation on fields set-- (pointing to the "current row" values in csra only). You would want to make them into parameters as with the rest of memory variables (which is not clear from the code which ones are memory variables).

Related

SSIS MySQL ADO.net SQL Task Input & Output

I am trying to use a SQL Task in Visual Studio SSIS to get two output values stored to variables.
I have done a range of Googling on the issue and have been able to get inserts working but I can't seem to see the output values to come out.
I am have tried using both '?' and #NameVariables but I am not having much luck.
SELECT `LocalUnitCode`,`IBDAuditCode`
FROM `tablename`.`provenance`
WHERE `DataCaptureTool` <> 'DataCaptureTool'
AND RIGHT(REVERSE(`IBDR_Source`),LENGTH(`IBDR_Source`)-LOCATE('_',REVERSE(`IBDR_Source`))) = ?;
OR
SELECT `LocalUnitCode`,`IBDAuditCode`
FROM `tablename`.`provenance`
WHERE `DataCaptureTool` <> 'DataCaptureTool'
AND RIGHT(REVERSE(`IBDR_Source`),LENGTH(`IBDR_Source`)-LOCATE('_',REVERSE(`IBDR_Source`))) = #Source;
OR
SET #LocalUnitCode =
(SELECT `LocalUnitCode`
FROM `tablename`.`provenance`
WHERE `DataCaptureTool` <> 'DataCaptureTool'
AND RIGHT(REVERSE(`IBDR_Source`),LENGTH(`IBDR_Source`)-LOCATE('_',REVERSE(`IBDR_Source`))) = #Source);
Not quite sure if the syntax is a problem or the parameter mapping or the result set needs changing. If I try and follow the guide that are using for SQL Server it does not appear to function correctly.
Any pointers in the right direction would be appreciated.
Thanks,
David
This is the code I am using in the SQL Statement:
SELECT ? = `LocalUnitCode`, ? = `IBDAuditCode`
FROM `ibdr_staging_K`.`provenance`
WHERE `DataCaptureTool` <> 'DataCaptureTool'
AND RIGHT(REVERSE(`IBDR_Source`),LENGTH(`IBDR_Source`)-LOCATE('_',REVERSE(`IBDR_Source`))) = ?;
Example of mapping variables to parameters in ADO.NET:
SQL:
SELECT #LocalUnitCode = `LocalUnitCode`, #AuditCode = `IBDAuditCode`
FROM `ibdr_staging_K`.`provenance`
WHERE `DataCaptureTool` <> 'DataCaptureTool'
AND RIGHT(REVERSE(`IBDR_Source`),LENGTH(`IBDR_Source`)-LOCATE('_',REVERSE(`IBDR_Source`))) = #Source;

passing an Array as a Parameter to be used in a SQL Query using the "IN" Command

Good Afternoon to All,
I have a question concerning on SQL Queries. is it possible to use an array as a parameter to a query using the "IN" command?
for example,
int x = {2,3,4,5}
UPDATE 'table_name' set 'field' = data WHERE field_ID IN (x)
the reason I am asking this is to avoid an iterative SQL Statement when I have to update data in a database.
I also thought of using a for each statement in for the UPDATE Query but I don't know if it will affect the performance of the query if it will slow down the system if ever 100+ records are updated.
I am using VB.Net btw.
My Database is MySQL Workbench.
I have gotten the answer. I just simply need to convert each elements to a String then concatenate it with a "," for each element. so the parameter that i will pass will be a string.
ANSWER:
int x = {2,3,4,5}
will become
string x = "2,3,4,5"
My Query string will become "UPDATE tablename SET field=value WHERE ID IN("&x&")"
Thank you to all who helped.
If you have the query in a variable (not a stored procedure) and you don't have a huge amount of ids, you could built your own IN. I haven't tested the speed of this approach.
This code won't compile, it's just to give you an idea.
query = "SELECT * FROM table WHERE col IN ("
For t = 0 TO x.Length-1
If t > 0 Then query &= ","
query &= "#var" & t
Next
query &= ")"
...
For t = 0 TO x.Length-1
cmd.Parameters.Add("#var" & t, SqlDbType.Int).Value = x(t)
Next
i am not familiar with mySQL, but when dealing with MSSQL, I normally have a split function in DB so that I can use it to split concatenated integer values as a table, at VB side, something like:
Dim myIds = {1, 2, 3, 4}
Dim sql = <sql>
SELECT m.* FROM dbo.tblMyData m
INNER JOIN dbo.fncSplitIntegerValues(#Ids, ',') t ON t.id = m.Id
</sql>.Value
Using con As New SqlConnection("My connection string..."),
cmd As New SqlCommand(sql, con)
cmd.Parameters.Add("#Ids", SqlDbType.VarChar).Value =
myIds.Select(Function(m) m.ToString).Aggregate(Function(m, n) m & "," & n)
con.Open()
Dim rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection)
While rdr.Read()
Console.WriteLine(rdr.GetValue(0))
' do something else...
End While
End Using
dbo.fncSplitIntegerValues is a db function to split concatenated integer varchar into integer Id with given separator.
it's important not to use plain sql, instead, use sql parameters.
Note: above sample is not tested...

SQL Server 2008: Error converting data type nvarchar to float

Presently troubleshooting a problem where running this SQL query:
UPDATE tblBenchmarkData
SET OriginalValue = DataValue, OriginalUnitID = DataUnitID,
DataValue = CAST(DataValue AS float) * 1.335
WHERE
FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND ZEGCodeID IN
(SELECT ZEGCodeID FROM tblZEGCode
WHERE(ZEGCode = 'C004') OR
(LEFT(ZEGParentCode, 4) = 'C004'))
Results in the following error:
Msg 8114, Level 16, State 5, Line 1
Error converting data type nvarchar to float.
The really odd thing is, if I change the UPDATE to SELECT to inspect the values that are retrieved are numerical values:
SELECT DataValue
FROM tblBenchmarkData
WHERE FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND ZEGCodeID IN
(SELECT ZEGCodeID
FROM tblZEGCode WHERE(ZEGCode = 'C004') OR
(LEFT(ZEGParentCode, 4) = 'C004'))
Here are the results:
DataValue
2285260
1205310
Would like to use TRY_PARSE or something like that; however, we are running on SQL Server 2008 rather than SQL Server 2012. Does anyone have any suggestions? TIA.
It would be helpful to see the schema definition of tblBenchmarkData, but you could try using ISNUMERIC in your query. Something like:
SET DataValue = CASE WHEN ISNUMERIC(DataValue)=1 THEN CAST(DataValue AS float) * 1.335
ELSE 0 END
Order of execution not always matches one's expectations.
If you set a where clause, it generally does not mean the calculations in the select list will only be applied to the rows that match that where. SQL Server may easily decide to do a bulk calculation and then filter out unwanted rows.
That said, you can easily write try_parse yourself:
create function dbo.try_parse(#v nvarchar(30))
returns float
with schemabinding, returns null on null input
as
begin
if isnumeric(#v) = 1
return cast(#v as float);
return null;
end;
So starting with your update query that's giving an error (please forgive me for rewriting it for my own clarity):
UPDATE B
SET
OriginalValue = DataValue,
OriginalUnitID = DataUnitID,
DataValue = CAST(DataValue AS float) * 1.335
FROM
dbo.tblBenchmarkData B
INNER JOIN dbo.tblZEGCode Z
ON B.ZEGCodeID = Z.ZEGCodeID
WHERE
B.FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND (
Z.ZEGCode = 'C004' OR
Z.ZEGParentCode LIKE 'C004%'
)
I think you'll find that a SELECT statement with exactly the same expressions will give the same error:
SELECT
OriginalValue,
DataValue NewOriginalValue,
OriginalUnitID,
DataUnitID OriginalUnitID,
DataValue,
CAST(DataValue AS float) * 1.335 NewDataValue
FROM
dbo.tblBenchmarkData B
INNER JOIN dbo.tblZEGCode Z
ON B.ZEGCodeID = Z.ZEGCodeID
WHERE
B.FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND (
Z.ZEGCode = 'C004' OR
Z.ZEGParentCode LIKE 'C004%'
)
This should show you the rows that can't convert:
SELECT
B.*
FROM
dbo.tblBenchmarkData B
INNER JOIN dbo.tblZEGCode Z
ON B.ZEGCodeID = Z.ZEGCodeID
WHERE
B.FieldDataSetID = '6956beeb-a1e7-47f2-96db-0044746ad6d5'
AND (
Z.ZEGCode = 'C004' OR
Z.ZEGParentCode LIKE 'C004%'
)
AND IsNumeric(DataValue) = 0
-- AND IsNumeric(DataValue + 'E0') = 0 -- try this if the prior doesn't work
The trick in the last commented line is to tack on things to the string to force only valid numbers to be numeric. For example, if you wanted only integers, IsNumeric(DataValue + '.0E0') = 0 would show you those that aren't.

Complex MySQL query issue

I have a somewhat complex mySQL query I am trying to execute. I have two parameters: facility and isEnabled. Facility can have a value of "ALL" or be specific ID. isEnabled can have value of "ALL" or be 0/1.
My issue is that I need to come up with logic that can handle the following scenarios:
1) Facility = ALL AND isEnabled = ALL
2) Facility = ALL AND isEnabled = value
3) Facility = someID AND isEnabled = ALL
4) Facility = someID AND isEnabled = value
The problem is that I have several nested IF statements:
IF (Facility = 'ALL') THEN
IF (isEnabled = 'ALL') THEN
SELECT * FROM myTable
ELSE
SELECT * FROM myTable
WHERE isEnabled = value
END IF;
ELSE
IF (isEnabled = 'ALL') THEN
SELECT * FROM myTable
WHERE facility = someID
ELSE
SELECT * FROM myTable
WHERE facility = someID AND isEnabled = value
END IF;
END IF;
I would like to be able to combine the logic in the WHERE clause using either a CASE statement or Conditional's (AND/OR) but I am having trouble wrapping my head around it this morning. Currently the query is not performing as it is expected to be.
Any insight would be helpful!
Thanks
You could do this...
SELECT
*
FROM
myTable
WHERE
1=1
AND (facility = someID OR Facility = 'ALL')
AND (isEnabled = value OR isEnabled = 'ALL')
However, this yields a poor execution plan - it's trying to find one size fits all, but each combination of parameters can have different plans depending on data, indexes, etc.
This means that it is better to build the query dynamically
SELECT
*
FROM
myTable
WHERE
1=1
AND facility = someID -- Only include this line if : Facility = 'ALL'
AND isEnabled = value -- Only include this line if : isEnabled = 'ALL'
I know it can feel dirty to use dynamic queries, but this is a good corner case as to when then really can excel. I'll go find a spectacularly informative link for you now. (It's a lot to read, but it's very worth learning from)
Link : Dynamic Search

Linq to Sql - Use sum in the where clause

I'm trying to select orders that have either over or under 2000 products ordered in them, depending on other values. I need to select the information from the Orders table, but check this value in the OrdersProducts table, specifically the sum of OrdersProducts.ProductQty. I also need to do this using predicate builder, because of other requirements. So far, I have this, but it isn't returning the results correctly. Its using nested Lambda expressions, which I didn't know I could do but I tried it and it works, but its not returning correct results.
Dim getOrders = From d In db.Orders _
Where d.Status = OrderStatus.Approved _
Select d
' Then a for loop adding parameters via Predicatebuilder...
If over2000 = True Then
' over 2000
predicate1 = predicate1.And(Function(d) (d.OrderProducts.Sum(Function(c) c.ProductQty > 2000)))
Else
' under 2000
predicate1 = predicate1.And(Function(d) (d.OrderProducts.Sum(Function(c) c.ProductQty < 2000)))
End If
basePredicate = basePredicate.Or(predicate1)
' End For loop
getOrders = getOrders.Where(basePredicate)
I removed some code for brevity but I think that gets the point across. How can I do this?? Thanks!
Try changing this:
(d.OrderProducts.Sum(Function(c) c.ProductQty > 2000))
to this:
(d.OrderProducts.Sum(Function(c) c.ProductQty) > 2000)
I haven't built this to test it, but it appears that it was currently trying to sum the results of a boolean comparison instead of summing the quantities and then comparing.