I'm writing a query to pull contact data based on whether someone is a "high donor" or "low donor", and my query works perfectly except for that it will include someone as both a highDonor and a lowDonor if they're in both categories, when we'd really want to just include them as a highDonor.
(For example: Jay Smith donated $1000 in June and $50 in July. Jay would be listed as both a highDonor and lowDonor.)
To fix this problem, I'm trying to exclude contacts from being lowDonors based on if they were already found to be highDonors. My original query unioned these subqueries, but when I try to alias the individual subqueries and reference highDonors in the second subquery, I get an error.
(Note: this is a shortened version of the full query that focuses in on the pieces that cause the error.)
This is the error I get: #1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'highDonors.contactId) as lowDonors ) as highAndLowDonors ' at line 23
#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'highDonors.contactId) as lowDonors ) as highAndLowDonors ' at line 23
SELECT DISTINCT
...
FROM
((
SELECT DISTINCT contactid,
"highDonor" AS highorlowdonor
FROM donation
WHERE donationdate > "2015-07-03"
AND donationamount BETWEEN 100 AND 9999.99)
AS highdonors
UNION ALL
(
SELECT DISTINCT contactid,
"lowDonor" AS highorlowdonor
FROM donation
WHERE donationdate > "2015-07-03"
AND donationamount BETWEEN 1 AND 99.99
WHERE contactid NOT IN highdonors.contactid)
AS lowdonors )
AS highandlowdonors
...
Any thoughts on what's causing the error here? Can I alias two subqueries like this and use the first one inside the second?
You cannot use the result from the first query in the second unless you repeat the first query.
But you could rewrite the query to group by the contactid
and get the maximum donationamount
. Put your logic in a CASE
looking at that maximum.
SELECT contactid,
CASE
WHEN max(donationamount) BETWEEN 100 AND 9999.99
THEN 'highDonor'
WHEN max(donationamount) BETWEEN 1 AND 99.99
THEN 'lowDonor'
END highorlowdonor
FROM donation
WHERE donationdate > '2015-07-03'
GROUP BY contactid
HAVING CASE
WHEN max(donationamount) BETWEEN 100 AND 9999.99
THEN 'highDonor'
WHEN max(donationamount) BETWEEN 1 AND 99.99
THEN 'lowDonor'
END IS NOT NULL;
(Note: Without the HAVING
this would include donors who have donated an amount < 1 or an 99.99 < amount < 100 or an amount > 9999.99 but with highorlowdonor
being null. Instead of using HAVING
I'd rather recommend to adapt your logic to use < (or >) rather than <= (or >=), which BETWEEN
is an alias for.)
And BTW: You're using double quotes ( "
) where you should use single quotes ( '
) (to enclose string and date literals).
You cannot alias two subqueries like this and use the first one inside the second. You can try the following:
SELECT DISTINCT contactid,
"highDonor" AS highorlowdonor
FROM donation
WHERE donationdate > "2015-07-03"
AND donationamount BETWEEN 100 AND 9999.99)
AS highdonors
UNION ALL
SELECT DISTINCT contactid,
"lowDonor" AS highorlowdonor
FROM donation
WHERE donationdate > "2015-07-03"
AND donationamount BETWEEN 1 AND 99.99
AND contactid NOT IN (select contact_id
FROM donation
WHERE donationdate > "2015-07-03"
AND donationamount BETWEEN 100 AND 9999.99)
A more efficient way would be store the first union select in a temp table and use that in the union and then use the same temp table in the second union select query to exclude the high donors.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.