I have 2 Query object in Coldfusion now I want to create a small report on account of these 2 queries
queries may look like
Q1
ID CODE NAME ACTIVE
and
Q2
CODE PRICE BOOKABLE
The code CODE
field is common key between these 2 queries. Now I want to get records are that are in Q1 but not in Q2 and vice versa, how many recodes are common in both queries where CODE is unique.
<cfquery name="Q1" datasource="test">
select * from users where code not in (select code from system)
</cfquery>
<cfquery name="Q2" datasource="test">
select * from system where code not in (select code from users)
</cfquery>
you can use QoQ to solve this.
<cfquery name="Q1" datasource="test">
select * from table1
</cfquery>
<cfquery name="Q2" datasource="test">
select * from table2
</cfquery>
<cfset q1code = valuelist(q2.code,"," )>
<cfset q2code = valuelist(q1.code,"," )>
<cfquery name="q3" dbtype="query" >
select * from q1 where code Not in(#q1code#)
</cfquery>
<cfquery name="q4" dbtype="query" >
select * from q2 where code Not in(#q2code#)
</cfquery>
<cfquery name="q5" dbtype="query" >
select * from q1,q2 where q1.code = q2.code
</cfquery>
Agree with other people, make the DB do the work. If these are in the same db, then you do this to get the records common to both tables:
SELECT Q1.ID
,Q1.CODE
,Q1.NAME
,Q1.ACTIVE
,Q2.PRICE
,Q2.BOOKABLE
FROM Q1, Q2
WHERE Q1.CODE = Q2.CODE
In order to do the first part of your question .. get the records that are in Q1 but not in Q2, you can do that with an outer_join if I am understanding you correctly. Syntax is different for all db's on doing outer joins. I always have to go look it up, so I'm not going to write it here.
another option is to union the two tables, and let cold fusion pull the reports on column_name = ''
select * from Q1 UNION SELECT * FROM Q2
-- you can't actually do this (select *) because of duplicate 'code' column in both dbs.
you'll have to specify the columns explicitly and rename the first one to Q1Code, then Q2Code.
then in CF you do
<cfif q2Code EQ ''> print Q1: #Q1CODE# <cfelse> print Q2: #Q2CODE# </cfif>
or maybe you want:
<cfif q1code EQ Q2code> yay they match</cfif>
Related
I am running a cfquery to pull records from a table:
<cfquery name="get_followups_monthly" datasource="#datasource#">
SELECT
a.DisplayName
, count(*) AS requested_count
FROM
users AS a
INNER JOIN
ticket_followup b ON b.requested_by = a.displayName
WHERE
a.active = 1 AND b.date_of_followup_request < '2022-02-01'
GROUP BY
a.DisplayName
ORDER BY requested_count DESC
</cfquery>
I would like to compare the dates returned in column b.date_of_followup_request to see if falls within the current month.
I looked through the builtin functions but don't see anything for that. How can this be accomplished?
I have two tables:
Users (2 columns): ID, DisplayName, Active
Ticket_Followups (4 colums): id, requested_by, requested_date, ticket_id
I am tryiwng to group all the similar records in the ticket_followup table, first by recordcount and then by displayName.
Here is what I have so far:
<cfquery name="active_users" datasource="#datasource#">
select * from users
where active='1'
</cfquery>
<cfloop query="active_users">
<cfquery name="get_followups" datasource="#datasource#">
select date_of_followup_request, requested_by, ticket_id
from ticket_followup
where requested_by = '#active_users.displayName#'
</cfquery>
<cfoutput>
<tr>
<td>#active_users.displayName#</td>
<td>#get_followups.recordcount#</td>
</tr>
</cfoutput>
</cfloop>
I am able to successfully show the output for the total records by user, but there is no order to the output. I would like to group it so that it shows the DisplayName with the highest recordcount first, descending in order.
How can I do that?
This is a SQL issue, CF is just displaying data after the data is gathered.
You need to do this in one query.
You need to associate the ticket follow ups by user ID, not by name (Name could change, but not the ID).
There's a table of tickets I assume, but we'll stick to your two tables.
First, the tables:
Users
----------
id
DisplayName
Active
Ticket_Followups
----------
id
requested_by_id (Users.id)
requested_date
ticket_id
You can technically join by name, but it's a much slower query and I've no idea how much data you have.
This query joins the two tables and gives you a count of ticket follow ups by user. You can add an ORDER BY statement before the GROUP BY depending on your needs.
SELECT
a.DisplayName
, count(*) AS requested_count
FROM
Users AS a
INNER JOIN
Ticket_Followups b ON b.requested_by_id = a.id
WHERE
a.active = 1
GROUP BY
a.id
If you don't do this in one query, then for every user that has an active ticket, you're making another query.
10 users, 11 queries
20 users, 21 queries
etc.
Updated 2022-02-15
Query using DisplayName with an ORDER BY clause. This should make it clearer that you're counting the tickets per user and not the number of users.
SELECT
a.DisplayName
, count(a.*) AS ticket_count
FROM
Ticket_Followups AS a
INNER JOIN
Users AS b ON b.DisplayName = a.DisplayName
WHERE
a.active = 1
ORDER BY
a.DisplayName DESC
GROUP BY
a.DisplayName
Output:
<cfoutput query="queryName">
<li>#queryName.DisplayName# - #queryName.ticket_count#</li>
</cfoutput>
I am reading a spreadsheet any trying to then run it in a query or Queries
<cfspreadsheet action="read"
src="#request.dropfolder##arguments.DSN#"
name="qryFromFile"
excludeHeaderRow="true"
headerrow="true">
<cfquery name="qryResult" dbtype="query">
SELECT EID
, CAST(#arguments.Config[2]# AS Decimal) AS [Value]
, 0 AS Invalid
, '<li><span><b>Comments:</b></span>' + Comments + ' on <time>' + [Date] + '</time></li>' AS Skyhook
FROM qryFromFile
ORDER BY EID
</cfquery>
Do I have to beild the table piece by piece?
To get CF to stuff the contents into a query, you need to use the "query" attribute, not the "name" attribute
<cfspreadsheet action="read"
src="#request.dropfolder##arguments.DSN#"
query="qryFromFile"
excludeHeaderRow="true"
... >
I am using CFSpreadsheet to read a .xlsx file.
The file has about 3000 duplicates which I can safely ignore so I thought I'd do a select distinct QoQ but once I do this, the results are ordered as if order by col_1, col_2 was added to the query which is a very bad thing.
<cfspreadsheet query = "qSheet" ...>
<cfquery dbtype="query" name = "qDistinctSheet">
select distinct
col_1
, col_2
from
qSheet
</cfquery>
<cfdump var = "#qDistinctSheet#">
If I remove distinct I get the expected results which SHOULD be:
[empty string]
Name
John
John
Adam
Steve
Bob
Bob
When I add distinct I get
[Empty String]
Adam
Bob
John
Name
Steve
Any idea how to prevent this unwanted ordering?
Edit
End solution is to apply a row number and use group by as suggested by Matt and Dan
<cfset ids = []>
<cfloop query="qSheet">
<cfset ids[qSheet.currentRow] = qSheet.currentRow>
</cfloop>
<cfset queryAddColumn(qSheet,"id",ids)>
<cfquery dbtype="query" name="qDistinct">
SELECT
col_1
, col_2
, min(ID) AS firstID
FROM
qSheet
GROUP BY
col_1
, col_2
ORDER BY
firstID
</cfquery>
You can use a GROUP BY option instead and use the ID row from the spreadsheet query
<cfquery dbtype="query" name="qDistinct">
SELECT
col_1
, col_2
, min(ID) AS firstID
FROM
qSheet
GROUP BY
col_1
, col_2
ORDER BY
firstID
We religiously use cfqueryparam in our SQL queries.
Some of my predecessors seem to have been a little overzealous when using it with direct values rather than variables.
Isn't
record_is_deleted_bt = <cfqueryparam cfsqltype="cf_sql_bit" value="0">
overkill? I mean, there's no chance for SQL injection and I don't think that using a bind variable here does anything helpful vis-à-vis improving performance in the database. Wouldn't it be just as reasonable to do
record_is_deleted_bt = 0
?
Is there any advantage to using cfqueryparam in such an instance, besides ingraining the habit of using it? Is there a disadvantage?
No, this is not overkill. cfqueryparam's first job is data binding. It helps in sql injection prevention is just the add-on bonus. The prepared statements through data binding execute faster. You are wrong to assume that it is there to help on sql attack prevention only.
Important Note:
I am adding Test case provided by #Dan Bracuk on an oracle db.
<cfquery name="without" datasource="burns">
select count(*)
from burns_patient
where patientid = 1
</cfquery>
<cfquery name="with" datasource="burns">
select count(*)
from burns_patient
where patientid = <cfqueryparam cfsqltype="cf_sql_integer" value="1">
</cfquery>
<cfscript>
TotalWithout = 0;
TotalWith = 0;
</cfscript>
<cfloop from="1" to="1000" index="i" step="1">
<cfquery name="without" datasource="burns" result="resultwithout">
select count(*)
from burns_patient
where patientid = 1
</cfquery>
<cfquery name="with" datasource="burns" result="resultwith">
select count(*)
from burns_patient
where patientid = <cfqueryparam cfsqltype="cf_sql_integer" value="1">
</cfquery>
<cfscript>
TotalWithout += resultwithout.executiontime;
TotalWith += resultwith.executiontime;
</cfscript>
</cfloop>
<cfdump var="With total is #TotalWith# and without total is #TotalWithout#.">
The with total ranges from 700 to 900 total milliseconds. The without total ranges from 1800 to 4500 milliseconds. The without total is always at least double the with total.