Can I perform the same functionality as this loop in sql? - coldfusion

What I'm doing is checking for a gap between several dates, and calling the result a duplicate if there is not a 14 day gap from the last non-duplicate result.
The code looks like this in coldfusion:
<cfset date_check = data.date_to_check />
<cfset counted = 1 />
<cfloop query="data" >
#dateformat( date_to_check )# <br>
<cfif abs( dateDiff('d', date_check , data.date_to_check ) ) gt 14 >
<cfset counted ++ />
<cfset date_check = data.date_to_check />
Not Duplicate
<cfelseif currentrow gt 1>
Duplicate
<cfelse>
Not Duplicate
</cfif>
</cfloop>
> #counted#
And the output, for example will be:
19-Jan-18 Not Duplicate
16-Jan-18 Duplicate
21-Oct-16 Not Duplicate
12-Oct-16 Duplicate
06-Oct-16 Not Duplicate
22-Sep-16 Duplicate
09-Aug-16 Not Duplicate
11-Jul-16 Not Duplicate
> 5
I tried using outer apply and joining the next row that is 14 days from the current row. But the problem with this approach is if I have a cluster, it "resets" the date each row, like this:
19-Jan-18 - not duplicate
16-Jan-18 - duplicate
10-Jan-18 - will give false duplicate ( compares itself to Jan 16 instead of Jan 19 )
The query for this is something like this:
SELECT
count(*)
FROM #item T1
OUTER APPLY (
SELECT TOP 1 *
FROM #item T2
WHERE T2.[index] < T1.[index]
ORDER BY T2.[index] DESC) T
WHERE DATEDIFF(DAY, T.[date], T1.[date]) > 14

I think an EXISTS subquery would be the most straightforward way to do it. If that isn't performant enough, then you could do a join for it, but I find that EXISTS is generally fast enough and much easier to read.
SELECT ID,
Name,
Date_To_Check,
CASE
WHEN EXISTS (
SELECT 1
FROM Table1 b
WHERE b.Date_To_Check < a.Date_To_Check
AND DATEDIFF(d,b.Date_To_Check,a.Date_To_Check) <= 14
)
THEN 1
ELSE 0
END AS isDuplicate
FROM Table1 AS a

Related

Access a coldfusion variable without knowing the name

Is there a syntax in coldfusion that will let me do that following?
<cfif DataSet2.RecordCount gt 0 >
<cfset append = #ArrayAppend(DataSet2Results,VAL(DataSet2.RecordCount))# >
</cfif>
Replacing the '2' in each case with an variable name (an index in a loop in this case).
So it would look like:
<cfif DataSet#index#.RecordCount gt 0 >
<cfset append = #ArrayAppend(DataSet#index#Results,VAL(DataSet#index#.RecordCount))# >
</cfif>
I know I can do a two dimensional array for this, but it would save me a slice of time if this can be done.
I found the answer to my own question. I used Variables["DataSet#index#"].recordcount and so on.

Parsing a query in coldfusion

I have a query as below which
<cfquery name="qryGetXXX" datasource="#sDataSource#">
SELECT COUNT(*) AS TotalCount,Quality.Qualitydesc
FROM QualityCheck INNER JOIN Quality
ON QualityCheck.QualityID = Quality.qualityID
WHERE DATEDIFF(d,DueDate,GETDATE()) >= 90
GROUP BY quality.qualityDesc
</cfquery>
will result in
1) *total count* 21 *QualityDesc* IO
2) *total count* 1 *QualityDesc* Max
3) *total count* 1 *QualityDesc* Min
4) *total count* 1 *QualityDesc* Other
5) *total count* 3 *QualityDesc* Reg
In order to get the first row I am using,
<cfif #qryGetXXX.RecordCount# gt 0 >
<cfloop query="qryGetXXX" startrow="1" endrow="1">
<cfset XXXTimeTotal =#qryGetXXX.TotalCount# >
</cfloop>
<cfelse>
<cfset XXTotal = 0 >
</cfif>
which is checking for the first the recordcount of the whole query but is there any way I can check whether the first row (i.e. startrow 1 and endrow 1) is has a value and then if the startrow 2 and endrow 2 has a value and so on? Can I put the results in an array and will that be easier?
Frank,
You are correct, i am new to coldfusion, hence all the confusion.The query provides me with the results i.e i have the result set as explained above, however i cannot figure out a way to check every row individually. For example i have to check if there are results for the first row and if it does i have to pass that value to my output, and if doesnot i have to put in no value was entered or '0'. I need to do this for the five rows and there will always only be 5 rows of results, which is why i was using start and endrow, however start and endrow donot allow me the flexibility to check for empty row values. In essence i would like to check the row as something like below.
<!--- check the first row of resuslt i.e. Max values ---!>
<cfif startrow1.endrow1 gt 0 >
<cfset nIOCount =#qryGetXXX.TotalCount# >
<cfelse>
<cfset nIOCount = '0'>
</cfif>
<!--- then check the second row resuslts Max ---!>
<cfif startrow2.endrow2 gt 0 >
<cfset nMaxCount =#qryGetXXX.TotalCount# >
<cfelse>
<cfset nMaxCount = '0'>
</cfif>
<!---Output the values---!>
Totals
<tr>
<th>IO</th>
<td>#nIoCount#</td>
</tr>
<tr>
<th>Max </th>
<td>#nMaxCount#</td>
</tr>
<tr>
I know i cannot reference startrow and endrow as i want, so i am looking for a way to reference each row individually in the result set some other way. Any suggestions?
thanks
That query/code is rough (I rendered it to something I could work with).
Your query: (if yours works just leave it as is (I'm making two assumptions below)).
<cfquery name="test" datasource="#sdatasource#">
select count(a.*) as totalcount, a.qualitydesc
from quality a, qualitycheck b
where a.qualityid = b.qualityid
and datediff(d,a.duedate,getdate()) >= 90
group by a.qualitydesc
</cfquery>
Then do your check if and sets like this: (instead of an array I did a struct (making more assumptions as well)).
<cfset totals = structnew()>
<cfif test.recordcount>
<cfoutput query="test">
<cfif test.totalcount neq "">
<cfset StructInsert( totals, test.QualityDesc, test.totalcount )>
<cfelse>
<cfset xxtotal = 0>
</cfif>
</cfoutput>
</cfif>
In fact, you can skip that nested if statement and for the xxtotal and do something else out of the loop leaving you with tighter code that looks like this:
<cfset totals = structnew()>
<cfif test.recordcount>
<cfoutput query="test">
<cfset StructInsert( totals, test.QualityDesc, test.totalcount )>
</cfoutput>
</cfif>
So if these are your targets:
1) totalcount 21 QualityDesc IO
2) totalcount 1 QualityDesc Max
3) totalcount 1 QualityDesc Min
4) totalcount 1 QualityDesc Other
5) totalcount 3 QualityDesc Reg
Then your looped values will look like this and any missing values or whatever will be bypassed (again you will need to do some checking down stream)...
totals.IO = 21
totals.Max = 1
totals.Min = 1
totals.Other = 1
totals.Reg = 3
Let me know if this helps and makes sense.
(Summary from comments...)
If you mean some of the descriptions, like "IO", are not included in query results at all, then that is what I suspected earlier. Since you are using an INNER join, the query will only return counts for descriptions that exist in both tables. If you want to include all descriptions, even if there is no match in "QualityCheck", you need to use an OUTER join instead. For example:
SELECT Quality.Qualitydesc
, COUNT(QualityCheck.QualityID) AS TotalCount
FROM Quality LEFT JOIN QualityCheck
ON QualityCheck.QualityID = Quality.qualityID
AND DATEDIFF(d,DueDate,GETDATE()) >= 90
GROUP BY quality.qualityDesc
Though as I mentioned on another thread, how you construct the filter can negatively impact the query's performance. See What makes a SQL statement sargable? for details and alternatives.
Side note, while you provided a lot of detail here, you omitted the most important part: .. the actual goal ;-) You will get faster and more accurate responses if you clearly summarize what you are trying to do first, then include the code.
The Golden Rule: Imagine You're Trying To Answer The Question
The XY Problem
How to Ask

Show where column equals a specific data?

I have a column(cse_dept) where it has integers , I would only like to show the columns where it equals 12 or 39.
Is there a way to do this?
<cfif (#GetCurrentUser.cse_dept# eq '12'39') >
<h1>test</h1>
</cfif>
It does not show me a error it just doesn't work the way I would like it.
You can use listFind. If the value of GetCurrentUser.cse_dept is 12 or 39 listFind will return the a number greater than 0
<cfif listFind('12,39', GetCurrentUser.cse_dept)>
<h1>test</h1>
</cfif>
listFind is case sensitive in case you were searching for something other than numbers. If you need a case-insensitve search you can use listFindNoCase
Alternatively you could check for each value separately
<cfif GetCurrentUser.cse_dept EQ 12 OR GetCurrentUser.cse_dept EQ 39>
<h1>test</h1>
</cfif>
If you want to check if GetCurrentUser.cse_dept is 12 or 39 for any result in your query you can do
<cfif listFind(valueList(getCurrentUser), 12) OR listFind(valueList(getCurrentUser), 39)>
<h1>test</h1>
</cfif>
There are a few ways to do this:
Method 1 - Query of Queries
<cfquery name="q1" dbtype="query">
select count(*) records
from GetCurrentUser
where cse_dept in (12,39)
</cfquery>
<cfif q1.records gt 0>
do something
</cfif>
Method 2 - List Functions
<cfif ListFind(ValueList(GetCurrentUser.cse_dept), 12)
+
ListFind(ValueList(GetCurrentUser.cse_dept), 39) gt 0>
do something
</cfif>
Method 3 - Array Functions
<cfif ArrayFind(GetCurrentUser['cse_dept'], 12)
+
ArrayFind(GetCurrentUser['cse_dept'], 39) gt 0>
do something
</cfif>
Method 2 is very similar to Matt's second suggstion. One difference is the use of a ValueList function. The second is that instead of using "or", I added the function results together. The results are the same.
Method 3 is probably the fastest. However, depending on where those numbers 12 and 39 come from, Method 1 might be a better approach.

Creating an Insert Statement for mysql table

I am creating a INSERT Starement for my table. Till now all going good and i have been able to create the Insert Statement. Only Issue Left is: It shows a trailing comma after the end of every single record. Can you guys have a look around what mess I am doing here
<cfset listcount = getQueryColumns(insertData)>
<cfset counter = 1>
<cfloop query="insertData">
<cfoutput>
INSERT INTO `mytable` (#listcount#)
VALUES(
<cfloop index="col" list="#listcount#">'#insertData[col][currentRow]#'
<cfif counter LT insertData.recordcount>,</cfif>
</cfloop>);<br><br>
</cfoutput>
<cfset counter++>
</cfloop>
Your error is due to the fact that you are incrementing your counter in the outer loop instead of the inner loop.
I think I've got it. I believe this is what you need:
<cfset listcount = getQueryColumns(insertData)>
<cfloop query="insertData">
<cfset counter = 1>
<cfoutput>
INSERT INTO `mytable` (#listcount#)
VALUES(
<cfloop index="col" list="#listcount#">'#insertData[col][currentRow]#'
<cfif counter LT listcount>,</cfif>
<cfset counter++>
</cfloop>);<br><br>
</cfoutput>
</cfloop>
What I changed is:
As Dan Bracuk pointed out, I moved <cfset counter++> inside the inner loop. I also moved <cfset counter = 1> inside the outer loop, as it will need to be reinitialized through successive INSERT statements.
I changed <cfif counter LT insertData.recordcount> to <cfif counter LT listcount>, as you don't want to iterate over the recordcount (this is why your commas stopped appearing after Priority, which was the 8th field). Instead, you want to iterate over the number of columns.
EDIT: See my more recent answer. I'm leaving this one in place because the comments were useful in the diagnosis.
I think Dan Bracuk is correct about your counter increment. But you might be able to simplify your code and avoid the <cfif > statement entirely if you you use the list attribute in <cfqueryparam >. For example:
<cfqueryparam value="#NAME_OF_LIST#" list="yes" >
By default this will put a comma between your list values before sending them to the database.
Check out the other attributes it takes at http://www.cfquickdocs.com/cf8/#cfqueryparam.

Strange bug in table

I'm in Coldfusion 8. I have a table that is produced by a loop. Very complex code but I put some of it here:
<cfloop array = #qrep.getColumnList()# index = "col">
<cfset l = l + 1>
<cfif l EQ tindx - 1>
<cfset prevcol= col>
</cfif>
<cfif linefold GT 0>
<cfset lmod = i%linefold>
<cfelse>
<cfset lmod = 1>
</cfif>
<!--- printing detail --->
<cfif l LE m AND repdetail NEQ 'n'>
<td class = "repsubthead"> Subtotal:
<b>#qrep[col][currentrow]#</b></td>
</cfif>
<!--- printing totals only; row labels --->
<cfif repdetail EQ 'n' AND l EQ tindx >
<cfset frowarr[footrow] = qrep[col][currentrow]>
<cfset footrow_1 = footrow - 1>
<cfif footrow EQ 1>
<td style = "font-size: 13px" > #qrep[col][currentrow]#</td>
<cfelseif frowarr[footrow] NEQ frowarr[footrow_1] >
<td style = "font-size: 13px;"> #qrep[col]currentrow]#</td>
<cfelse>
<cfset testrow = footrow>
<td class = "repsubthead" style = "padding-top: 10px"> Total #qrep[prevcol] currentrow]# </td>
</cfif>
.... lots more before we get to end of loop
This part of the code prints out a row label for each row. Further in the program there is a similar loop to print out the value for the row. Everything is working fine except for one problem I can't trace. An extra row is being inserted in one spot, with no data in it. Part of the table is here:
State: CT
AVS 25.00
COMB 15.00
Email2010 15.00
REF 75.00
STRLST01 22.00
extra row inserted here, height much smaller than other rows
STRLST04 50.00
Total CT 202.00
I have copied this table to a Libre Office document and zoomed in on the bad row. It is definitely there, and it contains a blinking item that looks like this: '
I cannot delete this item from the row in Libre Office, although I am able to delete the entire row. The blinking thing disappears when I put my cursor in another row.
I have checked both STRLST01 and STRLST04 in my MySQL database, and they seem fine, with no anomalies. I cannot find anywhere in my code where I would be inserting an extra row (altho admittedly the code is very complicated).
Has anyone seen something like this? Does anyone have a clue what might be causing this?
Just a shot in the dark here... but try sanitizing your table content. For example:
#htmlEditFormat(qrep[col][currentrow])#
This would be to rule out that the TR in "STRLST01" isn't getting processed as <TR>. I've seen dynamic tables like this one go haywire because the content gets interpreted as HTML.
MC
What is the generated HTML? Looking at the actual generated output rather than the rendered output could help you find if it's bad data being dumped into another row or if it's a bug in your HTML generation routine.
If it's an odd special character in your data, the HTMLEditFormat() or XMLFormat() functions should find it and deal with it. Or at least make it easier to troubleshoot.