• Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
    Dedicated community for Japanese speakers
  • 한국 커뮤니티
    Dedicated community for Korean speakers
Exit
0

How to loop through two queries at the same time?

Community Beginner ,
Oct 16, 2015 Oct 16, 2015

Copy link to clipboard

Copied

Hello everyone, I have two queries qryCustomer and qryStore. I have to loop through both at the same time. I tried to do this but that gave me duplicates.

<cfloop query="qryCustomer">

    <cfloop query="qryStore">

          Insert Into tblResults

          Values(#Name#,#Id#);

     </cfloop>

</cfloop>

If anyone knows how I can loop through both of them at the same time that way i can avoid inserting all ID's for the same Customer please let me know.

Thanks in advance.

Views

2.1K

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Oct 16, 2015 Oct 16, 2015

Copy link to clipboard

Copied

I've found that if you want to reference the outer loop query within the inner loop, you need to make explicit references:

<cfloop query="qryCustomer">

    <cfloop query="qryStore">

          Insert Into tblResults

          Values('#qryCustomer.Name#',#Id#);

     </cfloop>

</cfloop>

Although I'm not sure if "Name" is in qryCustomer or not, this is just an example. Also get into the habit of using cfqueryparam and you may want to explicitly reference both just to clarify to future programmers (or yourself):

<cfloop query="qryCustomer">

    <cfloop query="qryStore">

        <cfquery datasource="#ds#">

            Insert Into tblResults ( Name,Id )
            Values(<cfqueryparam value="#qryCustomer.Name#" cfsqltype="CF_SQL_VARCHAR" />,<cfqueryparam value="#qryStore.Id#" cfsqltype="CF_SQL_INTEGER" />);

  </cfquery>

     </cfloop>

</cfloop>

Lastly, another option that may be more efficient is to create a single joined query so you are only looping through a single result set.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Oct 19, 2015 Oct 19, 2015

Copy link to clipboard

Copied

Thank you for answering on my question. I always use cfqueryparam but this time that is not something that cause the problem. I have them in my code but I haven't include on this example. Your answer did not help me to solve my problem. Also your suggestion to join two queries does not work in my case. I'm reading values from two different queries after I sent all parameters with Ajax. Then I have to grab values from those two queries and Insert them in the table. So I have to loop through both queries at the same time and do Inset. I'm not sure if that's possible in coldfusion and what would be other way to do this.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Oct 19, 2015 Oct 19, 2015

Copy link to clipboard

Copied

I guess I would need examples because I'm not sure the goal. Can you create a pseudo dump of the two query contents and what you expect to be inserted? Something like:

qryCustomer

1: id=123, name="customer 1"

2: id=124, name="customer 2"

qryStore

1: storied=234, name="merchant 1", productid=345, productname="something"

2: storied=234, name="merchant 1", productid=346, productname="something else"

3: storied=235, name="merchant 2", productid=347, productname="something different"

inserted:

???

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Oct 19, 2015 Oct 19, 2015

Copy link to clipboard

Copied

Ok I will explain one more time with all details. I have screen where user can pick one or more customers or select All. Also on the same page User can pick Storage Unite(single ,multiple or All Storage Units). So when they pass the arguments to the next page I have two queries. Query Customers that will define number of selected customers and Query Storage that will define number of Storage Units. So User should not be able to submit anything if we have more customers than storage units. That's first thing that should be checked. If that is fine then we should loop through both quires Customers and Storage and Insert them in New Table. My current code looks like this:

<cffunction name="saveCustomers" access="remote" output="no" returnformat='JSON'>

  <cfargument name="AllCustomers" type="string" required="yes">

  <cfargument name="AllStorage" type="string" required="yes">

  <cfset fncResults = structNew()>

  <cfquery name="qryCustomers" datasource="Project1">

  Select ID, FirstName , LastName

  From Customers

  <cfif Arguments.AllCustomerss NEQ 'Y'>

        Where ID in (<cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.Customers#" list="true">)

  </cfif>

  </cfquery>

<cfquery name="qryStorage" datasource="Project1">

  Select StorageID, StorageNumber, NumberOfUses

  From Storage

  Where NumberOfUses <> '0'

  <cfif Arguments.AllStorage NEQ 'Y'>

  and StorageNumber in (<cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.Storage#" list="true">)

  </cfif>

  </cfquery>

  <cfloop query="qryCustomerss">

       <cfloop query="qryStorage">

       <cfif qryCustomers.ID NEQ qryAssign.CustomerID and qryStorage.NumberOfUses NEQ '0'>

       <cfset UsesLeft = #qryStorage.NumberOfUses# - 1>

       <cfquery name="AssignStorage" datasource="Project1">

            Insert Into ttAssignStorage(CustomerID, StorageNumber)

            Values (<cfqueryparam cfsqltype="cf_sql_integer" maxlength="20" value="#qryCustomers.ID#">,

            <cfqueryparam cfsqltype="cf_sql_varchar" maxlength="5" value="#qryStorage.StorageNumber#">);

       </cfquery>

       <cfif isDefined("StorageNumber")>

            <cfloop query="qryStorage">

                 <cfquery name="UpdateStorage" datasource="Project1">

                 Update ttStorage

                 Set

                 NumberOfUses = <cfqueryparam cfsqltype="cf_sql_varchar" maxlength="2" value="#UsesLeft#">

                 Where StorageNumber in (<cfqueryparam cfsqltype="cf_sql_varchar" value="#qryStorage.StorageNumber#" list="true">)

                 </cfquery>

            </cfloop>

     </cfif>

     </cfloop>

</cfloop>

This is my code that I'm using currently. I'm getting right values from my queries above but I'm having issues with looping thorough them and inserting those records. For example if I select all Customers and I have 150 of them, number of my storage units is 5. So my output will be each Customers is assign 5 times. What should not be done. I should get one Customer to be assign to one Storage Unit. So if you know what i'm doing wrong please let me know. My guess is that my cfloops are not at the right spot in my code.

Thanks in advance.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Oct 19, 2015 Oct 19, 2015

Copy link to clipboard

Copied

I would probably change the logic to do your customer query and then put the storage query within the customer loop and basically get one storage item at a time. Something like:

<cfquery name="local.qryCustomers" datasource="Project1">

Select ID, FirstName , LastName

From Customers

<cfif Arguments.AllCustomerss NEQ 'Y'>

  Where  ID in (<cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.Customers#" list="true">)

</cfif>

</cfquery>

<cftransaction>

<cfloop query="local.qryCustomerss">

  <cfquery name="local.qryStorage" datasource="Project1">

  Select StorageID, StorageNumber, NumberOfUses

  From Storage

  Where NumberOfUses <> '0'

  <cfif Arguments.AllStorage NEQ 'Y'>

   and StorageNumber in (<cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.Storage#" list="true">)

    </cfif>

</cfquery>

  <cfif local.qryStorage.recordCount EQ 0>

   <cfabort showerror="ARGH! Not enough inventory!" />

  </cfif>

  <cfset local.UsesLeft = val(local.qryStorage.NumberOfUses) - 1 />

  <cfquery datasource="Project1">

  Insert Into ttAssignStorage(CustomerID, StorageNumber)

  Values (

   <cfqueryparam cfsqltype="cf_sql_integer" maxlength="20" value="#local.qryCustomers.ID#">,

            <cfqueryparam cfsqltype="cf_sql_varchar" maxlength="5" value="#local.qryStorage.StorageNumber#">

  )

</cfquery>

  <cfquery datasource="Project1">

  Update ttStorage

  Set

   NumberOfUses = <cfqueryparam cfsqltype="cf_sql_varchar" maxlength="2" value="#UsesLeft#">

  Where StorageNumber in (<cfqueryparam cfsqltype="cf_sql_varchar" value="#qryStorage.StorageNumber#" list="true">)

</cfquery>

</cfloop>

</cftransaction>

I corrected some scoping issues. In CFFUNCTIONs, you either need to explicitly refer to the LOCAL scope or you need to declare all local variables as VAR before using them (<cfset var qryCustomers = 0 />...). I prefer the local scope so I don't have to worry about forgetting to define the variable as var. I also wrapped the loop within a cftransaction so this executes as an all or nothing event -- if inventory runs out while looping, all are put back the way they were.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Oct 19, 2015 Oct 19, 2015

Copy link to clipboard

Copied

Thank you this helped me a lot. I have one more question. How I can compare number of records from these two queries? If number of records in query Customers is Less or equal than Number of records in query Storage that's fine otherwise throw an error message?

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Advocate ,
Oct 19, 2015 Oct 19, 2015

Copy link to clipboard

Copied

You can use the recordcount property:

<cfif local.qryStorage.recordCount LT local.qryStorage.recordCount>

  <!--- do something --->

</cfif>

But the last loop logic a provided does not lend itself well to this and I'm not sure it'll work for you anyway because of your use of NumberOfUses.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Beginner ,
Oct 20, 2015 Oct 20, 2015

Copy link to clipboard

Copied

LATEST

Thank you I got my code to work finally.

Votes

Translate

Translate

Report

Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Resources
Documentation