Фильтровать второй подзапрос в UNION по результатам первого подзапроса - PullRequest
0 голосов
/ 04 июля 2018

Я пишу запрос, чтобы получить контактные данные, основываясь на том, является ли кто-то «высоким донором» или «низким донором», и мой запрос работает отлично, за исключением того, что он будет включать кого-то и как высокого донора, и низкого донора, если они мы находимся в обеих категориях, когда мы действительно хотим просто включить их в качестве highDonor.

(Например: Джей Смит пожертвовал 1000 долларов в июне и 50 долларов в июле. Джей будет указан как highDonor и lowDonor.)

Чтобы исправить эту проблему, я пытаюсь исключить контакты из списка lowDonors, если они уже были признаны как highDonors. Мой исходный запрос объединил эти подзапросы, но когда я пытаюсь присвоить псевдонимы отдельным подзапросам и ссылаться на highDonors во втором подзапросе, я получаю ошибку.

(Примечание: это укороченная версия полного запроса, которая фокусируется на фрагментах, вызывающих ошибку.)

Это ошибка, которую я получаю: #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
    ...

Есть мысли о том, что здесь вызывает ошибку? Могу ли я создать псевдоним для двух подзапросов, подобных этому, и использовать первый внутри второго?

Ответы [ 2 ]

0 голосов
/ 04 июля 2018

Нельзя использовать результат первого запроса во втором, если вы не повторите первый запрос.

Но вы можете переписать запрос в группу по contactid и получить максимум donationamount. Поместите свою логику в CASE, глядя на этот максимум.

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;

(Примечание: без HAVING это будет включать доноров, которые пожертвовали сумму <1 или 99,99 <сумма <100 или сумма> 9999,99, но с highorlowdonor, равным нулю. Вместо использования HAVING I ' Я скорее рекомендую адаптировать вашу логику для использования <(или>), а не <= (или> =), для которой BETWEEN является псевдонимом.)

И кстати: вы используете двойные кавычки ("), где вы должны использовать одинарные кавычки (') (для включения строковых и датных литералов).

0 голосов
/ 04 июля 2018

Вы не можете создать псевдоним двух подзапросов, подобных этому, и использовать первый внутри второго. Вы можете попробовать следующее:

    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)

Более эффективным способом было бы сохранить первый выбор объединения во временной таблице и использовать его в объединении, а затем использовать ту же временную таблицу во втором запросе выбора объединения, чтобы исключить старших доноров.

...