VBScript and SQL Server 2005 compare current row to previous row - sql-server

I am dealing with some legacy tech at my new job. Everything is either VBS or VBA and SQL Server 2005 is still running for at least 1 server, and 2008 on another. I can't change the tech I have to work with, so please don't respond with "Just use PowerShell" ... which is all I got from the Microsoft forums.
I need to modify an existing VBScript to iterate through the records of a table and give each page of a document a page number. The page number starts at 1 and resets to 1 every time the location folder changes, as defined by the row's value in the column Path. So I need to compare the current row's Path to the previous row's Path to see if there is a change.
From the specs request:
Use the following structure:
Outermost folder = Box field
Sub-folder = File Folder field
Docs within will each begin at "0000001"
Sub-folder = File Folder field
Docs within will each begin at "0000001"
Sub-folder = File Folder field
Docs within will each begin at "0000001"
Here is a very simple but effective Excel script that works, unfortunately I have to use VBScript so a third-party software can run the script:
=IF "Folder field in this row" = "Folder field in row above"
True = "above column" (beg doc of previous doc) + "pgcount of previous doc"
False = "1"
Here is the existing SQL statement from within the VBScript (Sorry for the naming convention - it is not my choice):
UPDATE tblpage
SET tblpage.UID = newtable.keyid
FROM tblpage inner join (SELECT PKEY, '" & prefix & "' + REPLICATE(0, " & padnum & " -
LEN(convert(varchar(" & padnum & "),(" & startnum & " + rank() OVER (ORDER
BY TBLDOC." & sortfield & ") + Page - 2)))) + CONVERT(nvarchar(" & padnum &
"), convert(varchar(" & padnum & "),(" & startnum & " + rank()
OVER (ORDER BY TBLDOC." & sortfield & ") + Page - 2))) AS keyid
FROM tblpage
inner join tbldoc on tblpage.id = tbldoc.id) as newtable ON newtable.pkey = tblpage.pkey;
variables taken from user input in VBScript - explanation
prefix - optional text prefix to the iterative number ie "SET" for "SET0000001"
padnum - number of 0s before iteration begins ie "000000" for "SET0000001"
startnum - starting number for the iteration ie "1" in "SET0000001"
sortfield - which table column to sort by ie a table's UID.
The above SQL does the iteration correctly but doesn't reset on new folder. I have been looking into SQL SERVER – How to Access the Previous Row and Next Row value in SELECT statement? – Part 2, but I am still quite confused.
My thoughts are that I join just the Path to the newtable based on the row's UID - 1, and then a case statement to compare them. If different, reset the page number. If the same, continue as normal.
Thanks!!

This answer comes from my old CS college roommate, but he doesn't have a Stack account(!?) so I'll post for him...
Even though the online docs for the OVER function are stamped 2008+, it actually does work just fine in 2005, as evidenced by the original posted query. This also means I can bypass all the nastiness of comparing previous row to current row by using PARTITION BY to reset on the chosen column Path
UPDATE tblpage
SET tblpage.UID = newtable.keyid
FROM tblpage inner join (SELECT PKEY, '" & prefix & "' + REPLICATE(0, " & padnum & " -
LEN(convert(varchar(" & padnum & "),(" & startnum & " + rank() OVER (
PARTITION BY TBLDOC.Path ORDER
BY TBLDOC." & sortfield & ") + Page - 2)))) + CONVERT(nvarchar(" & padnum &
"), convert(varchar(" & padnum & "),(" & startnum & " + rank()
OVER (PARTITION BY TBLDOC.Path ORDER BY TBLDOC." & sortfield & ") + Page - 2))) AS keyid
FROM tblpage
inner join tbldoc on tblpage.id = tbldoc.id) as newtable ON newtable.pkey = tblpage.pkey;

Related

Nested match_recognize query not supported in flink SQL?

I am using flink 1.11 and trying nested query where match_recognize is inside, as shown below :
select * from events where id = (SELECT * FROM events MATCH_RECOGNIZE (PARTITION BY org_id ORDER BY proctime MEASURES A.id AS startId ONE ROW PER MATCH PATTERN (A C* B) DEFINE A AS A.tag = 'tag1', C AS C.tag <> 'tag2', B AS B.tag = 'tag2'));
And I am getting an error as : org.apache.calcite.sql.validate.SqlValidatorException: Table 'A' not found
Is this not supported ? If not what's the alternative ?
I was able to get something working by doing this:
Table events = tableEnv.fromDataStream(input,
$("sensorId"),
$("ts").rowtime(),
$("kwh"));
tableEnv.createTemporaryView("events", events);
Table matches = tableEnv.sqlQuery(
"SELECT id " +
"FROM events " +
"MATCH_RECOGNIZE ( " +
"PARTITION BY sensorId " +
"ORDER BY ts " +
"MEASURES " +
"this_step.sensorId AS id " +
"AFTER MATCH SKIP TO NEXT ROW " +
"PATTERN (this_step next_step) " +
"DEFINE " +
"this_step AS TRUE, " +
"next_step AS TRUE " +
")"
);
tableEnv.createTemporaryView("mmm", matches);
Table results = tableEnv.sqlQuery(
"SELECT * FROM events WHERE events.sensorId IN (select * from mmm)");
tableEnv
.toAppendStream(results, Row.class)
.print();
For some reason, I couldn't get it to work without defining a view. I kept getting Calcite errors.
I guess you are trying to avoid enumerating all of the columns from A in the MEASURES clause of the MATCH_RECOGNIZE. You may want to compare the resulting execution plans to see if there's any significant difference.

wrong result in Apache flink full outer join

I have 2 data streams which were created from 2 tables like:
Table orderRes1 = ste.sqlQuery(
"SELECT orderId, userId, SUM(bidPrice) as q FROM " + tble +
" Group by orderId, userId");
Table orderRes2 = ste.sqlQuery(
"SELECT orderId, userId, SUM(askPrice) as q FROM " + tble +
" Group by orderId, userId");
DataStream<Tuple2<Boolean, Row>> ds1 = ste.toRetractStream(orderRes1 , Row.class).
filter(order-> order.f0);
DataStream<Tuple2<Boolean, Row>> ds2 = ste.toRetractStream(orderRes2 , Row.class).
filter(order-> order.f0);
I wonder to perform a full outer join on these 2 streams, and I used both orderRes1.fullOuterJoin(orderRes2 ,$(exp))
and a sql query containing a full outer join, as below:
Table bidOrdr = ste.fromDataStream(bidTuple, $("orderId"),
$("userId"), $("price"));
Table askOrdr = ste.fromDataStream(askTuple, $("orderId"),
$("userId"), $("price"));
Table result = ste.sqlQuery(
"SELECT COALESCE(bidTbl.orderId,askTbl.orderId) , " +
" COALESCE(bidTbl.userId,askTbl.orderId)," +
" COALESCE(bidTbl.bidTotalPrice,0) as bidTotalPrice, " +
" COALESCE(askTbl.askTotalPrice,0) as askTotalPrice, " +
" FROM " +
" (SELECT orderId, userId," +
" SUM(price) AS bidTotalPrice " +
" FROM " + bidOrdr +
" Group by orderId, userId) bidTbl full outer JOIN " +
" (SELECT orderId, userId," +
" SUM(price) AS askTotalPrice" +
" FROM " + askOrdr +
" Group by orderId, userId) askTbl " +
" ON (bidTbl.orderId = askTbl.orderId" +
" AND bidTbl.userId= askTbl.userId) ") ;
DataStream<Tuple2<Boolean, Row>> = ste.toRetractStream(result, Row.class).filter(order -> order.f0);
However, the result in some cases in not correct: imagine user A sells with a price to B 3 times, after that user B sells to A 2 times, the second time the result is:
7> (true,123,a,300.0,0.0)
7> (true,123,a,300.0,200.0)
10> (true,123,b,0.0,300.0)
10> (true,123,b,200.0,300.0)
the second and forth lines are the expected result of stream, but it will generate the 1st and 3rd lines too.
worth mentioning that coGroup is the other solution, yet I do not want to use windowing in this scenario, and a non-windowing solution is just accessible in bounded streams (DataSet).
Hint: orderId and userId will repeat in both streams, and I want to produce 2 rows in each action, containing:
orderId, userId1, bidTotalPrice, askTotalPrice AND
orderId, userId2, bidTotalPrice, askTotalPrice
Something like this is to be expected with streaming queries (or in other words, with queries executed on dynamic tables). Unlike a traditional database, where the input relations to a query are kept static during query execution, the inputs to a streaming query are being continuously updated -- and so the result must also be continuously updated.
If I understand the setup here, the "incorrect" results on lines 1 and 3 are correct up until the relevant rows from orderRes2 are processed. If those rows never arrive, then lines 1 and 3 will remain correct.
What you should expect is an eventually correct result, including retractions as necessary. You can reduce the number of intermediate results by turning on mini-batch aggregation.
This mailing list thread gives more insight. If I've misunderstood your situation, please provide a reproducible example that illustrates the problem.

Comboboxes visual basic 6

I have multiple comboboxes where users have the option of selecting an item. If no item is selected I insert NULL into SQL-SERVER:
if cboSchool.text="" then
g_strSQL = g_strSQL & "NULL,"
else
g_strSQL = g_strSQL & "'" & cboschool.itemdata(cboschool.listindex) & "',"
End if
My problem is as follow: Later on I allow the user to edit the information that they previously didn't select. So later on when they want to edit the information, I need to be able to have the application realize that there was a value or there wasn't a value in the table in (SQLSERVER), compare if its different from the value that was selected. And if the information is different then need to update the table. This is what my code looks for EDIT:
If g_RS!SchoolID <>cboSchool.ItemData(cboSchool.ListIndex)Then
g_strSQL2 = g_strSQL2 & " School ID = '" & cboSchool.ItemData (cboSchool.ListIndex) & "',"
End If
The problem Im seeing is that g_RS!SCHOOLID shows as "NULL", however it does notice that the value is different from cboschool.itemdata and it just skips to the end of the if statement. I don't understand how it doesn't see the difference.
If Val("" & g_RS!SchoolID) <> cboSchool.ItemData(cboSchool.ListIndex) Then
It's because of the null value that it doesn't see a difference.
You could have:
If g_RS!SchoolID <> "Hello world!" Then
g_strSQL2 = "DROP TABLE X"
Else
MsgBox ("g_RS!SchoolID = Hello world!")
End If
and as long as SchoolID is NULL you'd get a messagebox.
You could fix this with something like:
If Iif(IsNull(g_RS!SchoolID), "", g_RS!SchoolID) <> cboSchool.ItemData(cboSchool.ListIndex) Then
'do stuff
End If

HIbernate + MSSQL query compatibility

I need to get the latest "version" of a Task object for a given objectUuid. The Task is identified by its objectUuid, taskName and createdTimestamp attributes.
I had the following HQL query:
select new list(te) from " + TaskEntity.class.getName() + " te
where
te.objectUuid = '" + domainObjectId + "' and
te.createdTimestamp = (
select max(te.createdTimestamp) from " + TaskEntity.class.getName() + " teSub
where teSub.objectUuid = te.objectUuid and teSub.taskName = te.taskName
)
which ran and produced the correct results on H2 (embedded) and MySQL.
However after installing this code in production to MS SQL Server I get the following error:
An aggregate may not appear in the WHERE clause unless it is in a
subquery contained in a HAVING clause or a select list, and the column
being aggregated is an outer reference.
I tried to rewrite the query but HQL doesn't seem to support subqueries properly. My latest attempt is something like:
select new list(te) from " + TaskEntity.class.getName() + " te
inner join (
select te2.objectUuid, te2.taskName, max(te2.createdTimestamp)
from " + TaskEntity.class.getName() + " te2
group by te2.objectUuid, te2.taskName
) teSub on
teSub.objectUuid = te.objectUuid and teSub.taskName = te.taskName
where
te.objectUuid = '" + domainObjectId + "'
but of course it fails at the "(" after the join statement.
Since this is a very frequent type of query I cannot believe there is no solution that works with HQL+MSSQL.
Uh-oh. Can this be a typo?
max(teSub.createdTimestamp)
instead of
max(te.createdTimestamp)
in the subquery.

Access, Compilation errors and runtime

I have a Database that I need to use, but it has some errors which I have to fix.
Since I am not an expert in MS-Access, I can not figure out where the mistakes are.
The first error
Run-time. Could not find field '| 1' to which reference is made in the expression.
is thrown when pressing the print button.
Opening the debug, I found this piece of code:
Private Sub Pulsante40_Click()
If Me!Campo51 = False Then
Select Case [schede]![S_Stampa_Ordini].[ordinamento]
Case 1
DoCmd.OpenReport "Stampa Ordini BY DATA", , , " (DATA_AGG Between #" & Format$(Me.[Dal], "mm/dd/yyyy") & "# And #" & Format$(Me.[Al], "mm/dd/yyyy") & " 23:59#) AND Tipo = """ & Me.TipoL & """"
Case 2
DoCmd.OpenReport "Stampa Ordini BY CLIENTE", , , " (DATA_AGG Between #" & Format$(Me.[Dal], "mm/dd/yyyy") & "# And #" & Format$(Me.[Al], "mm/dd/yyyy") & " 23:59#) AND Tipo = """ & Me.TipoL & """"
Case 3
DoCmd.OpenReport "Stampa Ordini BY LAVORAZION", , , " (DATA_AGG Between #" & Format$(Me.[Dal], "mm/dd/yyyy") & "# And #" & Format$(Me.[Al], "mm/dd/yyyy") & " 23:59#) AND Tipo = """ & Me.TipoL & """"
Case 4
DoCmd.OpenReport "Stampa Ordini BY DATA_CONS", , , " (DATA_AGG Between #" & Format$(Me.[Dal], "mm/dd/yyyy") & "# And #" & Format$(Me.[Al], "mm/dd/yyyy") & " 23:59#) AND Tipo = """ & Me.TipoL & """"
End Select
FDipendente = 0
Else
DoCmd.OpenForm "FiltroStampa", , , , , A_DIALOG
End If
End Sub
It gives me error on line:
Select Case [schede]![S_Stampa_Ordini].[ordinamento]
The second error
Compile Error, could not find the method or data member
is thrown when I open the mask minutes and select
Legno, or Lavorazione Ext
code:
Private Sub Tipo_AfterUpdate()
Select Case Me.Tipo
Case "C"
Me.[SSMin-In].scheda.testo0.Caption = "Lavorazione:"
Case "L"
Me.[SSMin-In].scheda.testo0.Caption = "Cod.Prev.:"
Case "E"
Me.[SSMin-In].scheda.testo0.Caption = "Cod.Prev.:"
End Select
End Sub
It gives me the error on line:
Private Sub Tipo_AfterUpdate()
It has been days that I'm trying to solve the Database, or at least to start studying the visual basic to understand something. Unfortunately I only know java and my colleagues can not help me. Thank you in advance for an answer and I apologize if I was unclear or did not provide enough information.
It looks to me like your code is trying to refer to controls on your form, but in an invalid way (I can't quite understand what the code is trying to do because I don't read the language, and I don't know what controls you have on the form).
For example, to get the value of a combo box on a form, you would normally type something like Me.cboMyCombo.Value. To get the value of a field bound to this form, you would type something like Me!MyField or Me![My Field].Value.
Your calls to [schede]![S_Stampa_Ordini].[ordinamento] and Me.[SSMin-In].scheda.testo0.Caption look like they have a few too many methods on the end.
One way to find out what methods are acceptable is to start typing and let the pop-up menus guide you. For example, type Me. and see what pops up. In my example, cboMyCombo would be one of the items in the menu. Choose it, and you will see a new menu with Value as a choice.
You can also use the 'Expression Builder'.
You might want to try to copy your SQL into a query (or two). Make sure they actually produce the results you want. Then, you can call DoCmd.OpenQuery "qappYourNewQueryName". It is easier to read.
INSERT INTO [MIN-OUT]
( LAVORAZION, TIPO, MINUTI )
SELECT DISTINCTROW
[MIN-IN].LAVORAZION,
[MIN-IN].TIPO,
0 FROM [MIN-IN]
GROUP BY
[MIN-IN].LAVORAZION,
[MIN-IN].TIPO;
' What is this?
, ID_Dipendente )
SELECT DISTINCTROW
[MIN-IN].LAVORAZION,
[MIN-IN].TIPO,
[Forms]![Minuti].[dipendente] AS Espr1
FROM [MIN-IN]
GROUP BY
[MIN-IN].LAVORAZION,
[MIN-IN].TIPO,
[Forms]![Minuti].[dipendente];")

Resources