SQL Self-join со сравнением данных за разные дни

Мне нужно сравнить данные за два разных дня в SQL. И мне действительно нужно это в одном запросе, так как мне нужно использовать результаты в разбиении на страницы. Проблема в том, что когда я выполняю самосоединение, это приводит к дублированию столбцов, поскольку INNER JOIN является декартовым произведением.

Вот код скрипта sql

E.g.

SELECT * FROM `my_table` as t1 
INNER JOIN my_table t2 ON t1.quality = t2.quality
WHERE (
  t1.day = '2015-01-08' OR t1.day = '2015-01-09' OR 
  t2.day = '2015-01-08' OR t2.day = '2015-01-09'
)

Два вопроса:

  1. Как мне переписать, чтобы получить одну строку на JOIN по качеству?
  2. Будет ли он по-прежнему работать, если в одном из дней отсутствует какая-то соответствующая строка (по качеству)?

ИЗМЕНИТЬ

Вот ввод:

INSERT INTO my_table
(quality, quantity, day)
VALUES
('A', 1, '2015-01-15'),
('B', 2, '2015-01-15'),
('B', 0, '2015-01-10');

И желаемый результат:

QUALITY  | QUANTITY  | T1.QUANTITY - T2.QUANTITY
A           1          0 (or NULL?)
B           2          2

Объяснение:

Каждая дата содержит уникальные значения. Таким образом, мы видим только качество А и В. Для Б- есть подходящее Б на другую дату. Для А - нет. Следовательно, разница для B равна 2 (более высокая дата минус более низкая). Разница для A равна 0, потому что не из чего вычитать.


person valk    schedule 15.01.2015    source источник
comment
Поскольку вы получаете несколько значений для каждого JOIN качества, вам нужно решить, что с ними делать, например, выбрать максимум, минимум, сумму или что-то еще.   -  person jarlh    schedule 15.01.2015
comment
Можно отредактировать вопрос с ожидаемым результатом   -  person Pரதீப்    schedule 15.01.2015
comment
@NoDisplayName Я только что сделал.   -  person valk    schedule 15.01.2015


Ответы (1)


Вы получаете дублированные столбцы, потому что, поскольку они у вас есть, вы запрашиваете из T1 и T2. Поэтому, если вы явно не скажете, покажите мне только T1. *, он будет захватывать столбцы из ОБА ссылок на псевдонимы таблиц.

Поскольку ваш запрос выполняет операцию ИЛИ с датами, вы, вероятно, также получите декартовский результат.

Теперь вы знаете структуру вашей таблицы, но вам может быть лучше с явным запросом, например...

SELECT
      t1.day,
      t2.day as OtherDay,
      t1.quality,
      t1.anotherColumn,
      t2.OtherAnotherColumn,
      t1.thirdColumn,
      t2.OtherThirdColumn
   FROM 
      my_table t1
         join my_table t2
            on t1.quality = t2.quality
           AND t2.day = '2015-01-09'
   where
      t1.day = '2015-01-08' 

Имейте индекс в своей "my_table" на основе (день, качество) для оптимизации запроса. И вы можете просто добавлять попарно столбцы, которые вы пытаетесь сравнить между днями 1 и 2. T1 будет возвращать только те, которые связаны с первым днем, а псевдоним T2 будет отображаться только для совпадающих записей для второй даты.

Теперь, если есть только записи на стороне T1 без соответствующей записи T2 для рассматриваемого качества и даты, но вы все равно хотите их увидеть, просто измените JOIN на LEFT JOIN.

person DRapp    schedule 15.01.2015
comment
Привет @DRapp, это здорово, спасибо!! Чего мне не хватало, так это того, что AND в JOIN. Могу ли я спросить, есть ли способ добавить также A к результату? Я знаю, что не совсем ясно выразился в своем вопросе, но затем отредактировал его. - person valk; 15.01.2015
comment
@valk, если вы имеете в виду получение только определенного качества A, то добавьте это в свое предложение OUTER WHERE, и тогда он принудительно заставит T2, поскольку он полагается на значение T1, которым вы сейчас ограничиваете качество. - person DRapp; 15.01.2015