2016-03-02 2 views
2

я есть таблица Transactions, которая выглядит примерно так:MySQL из «не» без значения столбца

id Type   Field  ObjectId NewValue  
1 AddLink  HasMember 4567  someDomain/someDirectory/1231 
2 AddLink  HasMember 4567  someDomain/someDirectory/1232 
3 AddLink  HasMember 4567  someDomain/someDirectory/1233 
4 DeleteLink HasMember 4567  someDomain/someDirectory/1231 

Числовой конец «NewValue» является то, что я заинтересован в

В. Подробно, мне нужны те записи, где у меня есть запись, где тип - «AddLink», и где не существует более новой записи типа «DeleteLink», то есть записи с id = 2 или 3 (с 4 удалений 1)

" ObjectId ", а также числовой бит" NewValue ", оба являются идентификаторами записи таблицы «билеты», и мне нужны соответствующие билеты.

я попытался это:

SELECT `Tickets`.* FROM `Transactions` AS `addedLinks` 
    LEFT JOIN `Tickets` ON RIGHT (`addedLinks`.`NewValue`, 4) = `Tickets`.`id` 
    WHERE `addedLinks`.`Type` = 'AddLink' 
     AND `addedLinks`.`Field` = 'Hasmember' 
     AND `addedLinks`.`ObjectId` = '4567' 

     AND NOT RIGHT (`addedLinks`.`NewValue`, 4) in (

      SELECT `Tickets`.* FROM `Transactions` AS `deletedLinks` 
      LEFT JOIN `Tickets` ON RIGHT (`deletedLinks`.`NewValue`, 4) = `Tickets`.`id` 
      WHERE `deletedLinks`.`Type` = 'DeleteLink' 
       AND `addedLinks`.`id` < `deletedLinks`.`id` 
       AND `deletedLinks`.`Field` = 'Hasmember' 
       AND `deletedLinks`.`ObjectId` = '4567') 

Это дает мне:

SQL Error (1241): Operand should contain 1 column(s) 

Если я не получил что-то неправильно, то проблема заключается в

RIGHT (`addedLinks`.`NewValue`, 4) 

в «И НЕ ... in() ".

Может ли кто-нибудь указать мне правильное направление здесь?

[EDIT] Благодаря David K-J, следующие работы:

SELECT `Tickets`.* FROM `Transactions` AS `addedLinks` 
    LEFT JOIN `Tickets` ON RIGHT (`addedLinks`.`NewValue`, 4) = `Tickets`.`id` 
    WHERE `addedLinks`.`Type` = 'AddLink' 
     AND `addedLinks`.`Field` = 'Hasmember' 
     AND `addedLinks`.`ObjectId` = '5376' 

     AND NOT (RIGHT (`addedLinks`.`NewValue`, 4)) in (

       SELECT `id` FROM `Transactions` AS `deletedLinks` 
       WHERE `deletedLinks`.`Type` = 'DeleteLink' 
        AND `addedLinks`.`id` < `deletedLinks`.`id` 
        AND `deletedLinks`.`Field` = 'Hasmember' 
        AND `deletedLinks`.`ObjectId` = '5376') 

, но я не понимаю, почему?

+0

@PetSerAl, к сожалению, приводит к такой же ошибке. – Burki

+3

Я думаю, что ваш subselect только хочет выбрать поле 'id', то есть' Tickets. * '->' Tickets.id' –

+0

Либо замените ключевое слово 'IN' на' EXISTS' и удалите 'RIGHT (' 'addedLinks'' .''NewValue'', 4) 'или изменить ваш подзапрос, чтобы он возвращал только один столбец. –

ответ

1

Проблема заключается в том, что ваш суб-выбор, поскольку вы используете его для предоставления значения предложения IN, ваш подвыбор должен выбрать только поле id, то есть Transactions.* - >Transactions.id

Итак, вы в конечном итоге с:

... 
AND NOT (RIGHT (`addedLinks`.`NewValue`, 4)) IN 
    SELECT id FROM Transactions AS deletedLinks WHERE 
... 

Причина этого заключается в том, что IN требует список для сравнения с, так foo IN (1,2,3,4,5). Если ваш подзапрос выбирает несколько полей, результирующий список является концептуально списком списков (AoAs), например [1, 'a'], [2, 'b'], [3, 'c'], и он будет жаловаться на вас =)

0

А что так сложно и с подзапроса ... сделать его проще, будет гораздо быстрее

CREATE TEMPORARY TABLE `__del_max` 
    SELECT `NewValue`, MAX(`id`) as id FROM tickets 
    WHERE type = 'DeleteLink' 
     GROUP BY NewValue; 

CREATE INDEX _nv ON __del_max(`NewValue`) 

SELECT * FROM `tickets` 
    LEFT OUTER JOIN `__del_max` ON tickets.NewValue = __del_max.NewValue AND __del_max.id > tickets.id 
WHERE __del_max.id IS NULL 

Вы можете иметь его в сингл, большой присоединиться, но было бы полезно иметь его в ТМП таблицу, так что вы можете добавить индекс;)

+0

Я использую мое заявление выше в рекурсивной функции, которая должна найти дочерние элементы. Мне не нравится ваше предложение для этой работы (что мало значит), но больше всего это не объясняет, что я сделал неправильно? – Burki

+0

Хм ... это очень просто, IN может содержать много значений IN (1,2,3), но только один столбец, например. IN (x), но NOT - IN (x, y) Если вы хотите продолжить свой путь, вам понадобится OUTER JOIN. – Slawek

Смежные вопросы