MySQL запрос с соединением по производной таблице, содержащей group by, возвращает самую последнюю связанную запись - PullRequest
0 голосов
/ 27 мая 2011

Привет всем
У меня есть запрос MySQL, который использует соединения на пару производных таблиц. Один из производных запросов работает отлично, и я получаю правильное количество возвращаемых строк.
Но я также пытаюсь отобразить дополнительную информацию из связанной таблицы для каждой строки, и именно здесь я борюсь. Я прочитал здесь несколько других вопросов с похожими вопросами, но мне не удалось применить его к моему запросу.

Вот запрос:

SELECT `adbookings`.`company_id`, `companies`.`company_name`, `adbookings`.`run`, `adbookings`.`bill_freq`, `adbookings`.`currency`, FORMAT(`adinserts`.`rate`, 2) AS `rate`, `publications`.`title`, CONCAT(FLOOR(CAST(UNIX_TIMESTAMP()-`invoices`.`last_invoice_stamp` AS SIGNED INTEGER)/86400), ' days ago') AS `last_invoice_days_ago`, `invoices`.`last_invoice_no`, `invoices`.`last_invoice_reference`
FROM `adinserts` 
INNER JOIN 
(
SELECT `publications`.`publication_id`, `publications`.`art_stamp`, `publications`.`title`
FROM `publications`
LEFT JOIN `adinserts` ON `publications`.`publication_id`=`adinserts`.`publication_id` AND `adinserts`.`invoice_id` IS NOT NULL
WHERE `publications`.`publication_stamp`>=UNIX_TIMESTAMP('2010-01-01 00:00:00')
GROUP BY `publications`.`publication_id`
HAVING COUNT(`adinserts`.`invoice_id`)>0
) AS `publications` ON `adinserts`.`publication_id`=`publications`.`publication_id`
LEFT JOIN `adbookings` ON `adinserts`.`booking_id`=`adbookings`.`booking_id` 
LEFT JOIN
(
SELECT `company_id`, CONCAT_WS('', `prefix`, `invoice_id`, `suffix`) AS `last_invoice_no`, MAX(`invoices`.`invoice_stamp`) AS `last_invoice_stamp`, `reference` AS `last_invoice_reference` 
FROM `invoices`
GROUP BY `invoices`.`company_id`
) AS `invoices` ON `adbookings`.`company_id`=`invoices`.`company_id`
LEFT JOIN `companies` ON `adbookings`.`company_id`=`companies`.`company_id` 
WHERE `adinserts`.`invoice_id` IS NULL AND `adinserts`.`cancel_stamp` IS NULL AND `adinserts`.`rate`>0
ORDER BY `publications`.`art_stamp`, `companies`.`company_name`

Моя проблема со второй производной таблицей ... LEFT JOIN (...) AS invoices

Я пытаюсь получить invoice_stamp самого последнего связанного счета для этой компании, используя MAX (invoice_stamp). Это, кажется, работает и возвращает связанную запись с наибольшим значением invoice_stamp (метка времени Unix).

Но я также пытаюсь получить совпадающие invoice_id и справочные поля этой записи, возвращаемые агрегатной функцией MAX (). Но поля invoice_id и reference не соответствуют записи, возвращаемой функцией MAX ().

Кто-нибудь знает, как я могу получить полную информацию о записи, возвращаемой статистической функцией в производной таблице?

Ответы [ 3 ]

1 голос
/ 27 мая 2011

Вы не можете легко.Посмотрите этот очень похожий вопрос здесь, с кем-то, кто пытается соответствовать последней оценке:

Mysql query query

0 голосов
/ 28 мая 2011

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

SELECT `adbookings`.`company_id`, `companies`.`company_name`, `adbookings`.`run`, `adbookings`.`bill_freq`, `adbookings`.`currency`, FORMAT(`adinserts`.`rate`, 2) AS `rate`, `publications`.`title`, 
CONCAT(FLOOR(CAST(UNIX_TIMESTAMP()-SUBSTRING_INDEX(`invoices`.`last_invoice`, '-', 1) AS SIGNED INTEGER)/86400), ' days ago') AS `last_invoice_days_ago`, 
SUBSTRING_INDEX( SUBSTRING_INDEX(`invoices`.`last_invoice`, '-', 3), '-', -1) AS `last_invoice_no`, 
SUBSTRING_INDEX( SUBSTRING_INDEX(`invoices`.`last_invoice`, '-', 4), '-', -1) AS `last_invoice_reference` 
FROM `adinserts` 
INNER JOIN 
(
SELECT `publications`.`publication_id`, `publications`.`art_stamp`, `publications`.`title`
FROM `publications`
LEFT JOIN `adinserts` ON `publications`.`publication_id`=`adinserts`.`publication_id` AND `adinserts`.`invoice_id` IS NOT NULL
WHERE `publications`.`publication_stamp`>=UNIX_TIMESTAMP('2010-01-01 00:00:00')
GROUP BY `publications`.`publication_id`
HAVING COUNT(`adinserts`.`invoice_id`)>0
) AS `publications` ON `adinserts`.`publication_id`=`publications`.`publication_id`
LEFT JOIN `adbookings` ON `adinserts`.`booking_id`=`adbookings`.`booking_id` 
LEFT JOIN
(
SELECT `company_id`, MAX(CONCAT_WS('-', `invoice_stamp`, `invoice_id`, CONCAT_WS('', `prefix`, `invoice_id`, `suffix`), `reference`)) AS `last_invoice` 
FROM `invoices`
GROUP BY `invoices`.`company_id`
) AS `invoices` ON `adbookings`.`company_id`=`invoices`.`company_id`
LEFT JOIN `companies` ON `adbookings`.`company_id`=`companies`.`company_id` 
WHERE `adinserts`.`invoice_id` IS NULL AND `adinserts`.`cancel_stamp` IS NULL AND `adinserts`.`rate`>0
ORDER BY `publications`.`art_stamp`, `companies`.`company_name`

Итак, во 2-й производной таблице я собираю конкатенацию нужных мне данных из этой конкретной строки, затем запускаю MAX) на этом.
Затем в родительском запросе я использую функцию подстроки для "взрыва" на основе моего разделителя.

Это ужасный, ужасный метод, к которому приходится прибегать в базе данных отношений: (
Но это работает:)

0 голосов
/ 27 мая 2011

Исходя из того, что AdInsert является отношением 1: 1 к публикациям, а 1: 1 - к бронированию и, в конечном итоге, к компании, нам не нужно выполнять обратную ссылку на AdInserts с тем же идентификатором в поисках счета, который мы ». Я просто буду игнорировать.

ЭТИ должны быть квалифицированными рекламными вставками, которые вы ищете и, в конечном счете, хотите получить дополнительную информацию о бронировании / компании. Используя предварительный запрос для получения всех предварительных рекламных вставок и последнего штампованного счета-фактуры для компании, он МОЖЕТ быть присоединен к счетам с помощью этого идентификатора счета и отметки времени.

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

SELECT STRAIGHT_JOIN
      PreQuery.Company_ID,
      PreQuery.Company_Name,
      PreQuery.Run,
      PreQuery.Bill_Freq,
      PreQuery.Currency,
      PreQuery.Rate,
      PreQuery.Publication_ID,
      PreQuery.Booking_ID,
      PreQuery.Art_Stamp,
      PreQuery.Title,
      Invoices.prefix, 
      Invoices.invoice_id, 
      Invoices.suffix,
      Invoices.invoice_stamp,
      Invoices.reference 
   from 
      ( SELECT 
              ab.company_id,
              c.Company_Name
              ab.run,
              ab.bill_freq,
              ab.currency,
              ai.publication_id,
              ai.booking_id,
              format( ai.rate, 2 ) Rate,
              p.title,
              p.art_stamp,
              ( select MAX( invoices.invoice_stamp ) 
                    from Invoices 
                    where Invoices.Company_ID = c.Company_ID ) As LastInvoiceStamp;
           from
              adinserts ai
                 JOIN publications p
                    ON ai.publication_id = p.publication_id
                    and p.publication_stamp >= UNIX_TIMESTAMP('2010-01-01 00:00:00'

                 JOIN adBookings ab
                    ON ai.Booking_ID = ab.Booking_ID

                    JOIN Company c
                       ON ab.Company_id = c.Company_ID

           where
                  ai.Invoice_ID is null
              and ai.Cancel_Stamp is null
              and ai.rate > 0 ) PreQuery

      LEFT JOIN Invoices
         ON PreQuery.Company_ID = Invoices.Company_ID
         AND PreQuery.LastInvoiceStamp = Invoices.Invoice_Stamp

Возможно, вам придется применить COALESCE () к полям счетов в случае, если отсутствует нулевой предварительный счет для компании, но я думаю, что это очень ЗАКРЫТО с тем, что вы ищете.

...