Как сравнить значения из двух отдельных запросов, но не использовать внутренний цикл?
Я работаю над своим проектом, где я должен сравнить значения из базы данных со значениями из файла.csv. я использовал 'cfhttp'
чтобы преобразовать мой.csv в запрос, а затем я перебираю этот запрос и другой запрос, который использовал для получения значений из БД. Внутри этих двух циклов я использовал операторы if, чтобы сравнить мои значения и проверить, совпадают ли они. Затем я сохранил их в списках и использую эти списки в тегах cfquery для своего обновления. У меня есть 14k записей в БД и примерно столько же записей в моем файле.csv. Мой текущий код занимает менее 2 минут, чтобы вывести записи из списка на экран для целей тестирования. Я все еще не проверял, сколько времени займет обновление. Прежде чем запускать обновление, я хотел бы посмотреть, порекомендует ли кто-нибудь из вас какой-либо другой подход к моему проекту? Могу ли я сократить время выполнения до меньшего, чем сейчас? Вот мой код, который у меня есть:
<cfhttp name="records" columns="A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X" method="get" url="http://path to csv/temp.csv"/>
<cfquery name="getRecords" datasource="test">
Select s.ID, f.URID, s.UR_NUMBER, CODE, f.FIELD
From USERS s
Left Outer Join MAPS f
ON s.ID = f.URID
</cfquery>
<cfset NumA = "">
<cfset NumB = "">
<cfset NumC = "">
<cfset NumD = "">
<cfset NumE = "">
<cfset updNumD = "">
<cfset updNumE = "">
<cfloop query="records">
<cfloop query="getRecords">
<cfif records.A EQ getRecords.UR_NUMBER>
<cfif records.W NEQ getRecords.CODE>
<cfif records.W EQ 'A'>
<cfset NumA = ListAppend(NumA,"#records.A#")>
<cfelseif records.W EQ 'B'>
<cfset NumB = ListAppend(NumB,"#records.A#")>
<cfelse>
<cfset NumC = ListAppend(NumC,"#records.A#")>
</cfif>
</cfif>
<cfif getRecords.URID EQ ''>
<cfif records.W EQ 'D'>
<cfset NumD = ListAppend(NumD, "#getRecords.ID#")>
<cfelseif records.W EQ 'E'>
<cfset NumE = ListAppend(NumE, "#getRecords.ID#")>
</cfif>
<cfelse>
<cfif records.W EQ 'E'>
<cfset updNumD = ListAppend(updNumD, "#getRecords.URID#")>
<cfelseif records.W EQ 'D'>
<cfset updNumE = ListAppend(updNumE, "#getRecords.URID#")>
</cfif>
</cfif>
</cfif>
</cfloop>
</cfloop>
Здесь я выкидываю свои списки на экран:
<cfdump var="#NumA#">
<cfdump var="#NumB#">
<cfdump var="#NumC#">
<br>
<cfdump var="#NumE#">
<cfdump var="#NumD#">
<br>
<cfdump var="#updNumE#">
<cfdump var="#updNumD#">
Также мне было интересно, можно ли с помощью тега cfhttp выйти только из тех столбцов, которые мне нужны из моего.csv? Теперь я собираю все столбцы из моего.csv, даже если я использую только два из них - столбцы A и W. Также возможно присоединение к запросу из 'cfhttp'
на мой запрос из БД? Если кто-нибудь может дать мне совет по этому проекту, пожалуйста, дайте мне знать.
1 ответ
Поэтому я думаю, что вы заинтересованы только в данных, где records.A
равно getRecords.UR_NUMBER
, Вы можете использовать Query of Queries, чтобы получить пересечение двух наборов данных. Что-то вроде:
<cfquery name="intersection" dbtype="query">
select *
from records, getRecords
where records.A = getRecords.UR_NUMBER
</cfquery>
Это должно дать вам объединенный набор данных, который вы можете затем просмотреть и построить свои списки. Как отметил Мэтт Буш в комментариях, операции со списком выполняются медленно, поэтому arrayAppend будет быстрее.
Если Query или Query слишком медленный, вам может потребоваться преобразовать один из наборов записей в структуру (из пар ключ-значение), так как поиск выполняется быстрее. Например:
<cfscript>
// convert to structs as key lookups are fast
dbData = {};
for (row in getRecords) {
dbData[row.UR_NUMBER] = row;
}
csvData = {};
for (row in records) {
if (structKeyExists(dbData, row.A)) {
// we have a match, so build the lists here...
writeDump(dbData[row.A]);
}
}
</cfscript>