#sql #sql-server
#sql #sql-сервер
Вопрос:
Привет, мне трудно объединить две записи (из одной таблицы) в одном запросе. Идея в том, что столбец DATE_FIELD — это тип даты, а ColA — целочисленный тип данных.
Для дополнительной иллюстрации моего запроса я прикрепил изображение ниже
1.) — это необработанная таблица. 2.) Является желаемым результатом.
PS Фильтр для DATE_FIELD — это не простое предложение «ГДЕ DATE_FIELD В».
Например, я хотел получить DATE_FIELD=30.12.2013. Затем мне нужно также получить предыдущее поле Sept DATE_FIELD, которое является 9/30/2013 программно, используя этот запрос, который я получил из Интернета:
CASE
WHEN MONTH(DATE_FIELD) < 10
THEN
(cast(CAST((DATE_FIELD) - 1) as char(4)) RIGHT('00' LTRIM(09),2) RIGHT('00' LTRIM(30),2) AS Date))
ELSE
( cast(CAST((YEAR(DATE_FIELD)) as char(4)) RIGHT('00' LTRIM(09),2) RIGHT('00' LTRIM(30),2) AS Date))
END
Вот мой текущий sql-скрипт (который не может получить эквивалент ColA для предыдущего фильтра Sept:
SELECT DATE_FIELD, ColA,
CASE
WHEN MONTH(DATE_FIELD) < 10
THEN
(cast(CAST((YEAR(DATE_FIELD) - 1) as char(4)) RIGHT('00' LTRIM(09),2) RIGHT('00' LTRIM(30),2) AS Date))
ELSE
( cast(CAST((YEAR(DATE_FIELD)) as char(4)) RIGHT('00' LTRIM(09),2) RIGHT('00' LTRIM(30),2) AS Date))
END AS PREVIOUS,
(
SELECT ColA
FROM TABLE_A
WHERE DATE_FIELD =
CASE
WHEN MONTH(DATE_FIELD) < 10
THEN
(cast(CAST((YEAR(DATE_FIELD) - 1) as char(4)) RIGHT('00' LTRIM(09),2) RIGHT('00' LTRIM(30),2) AS Date))
ELSE
( cast(CAST((YEAR(DATE_FIELD)) as char(4)) RIGHT('00' LTRIM(09),2) RIGHT('00' LTRIM(30),2) AS Date))
END
) AS PYE_colA
FROM TABLE_A
WHERE DATE_FIELD = '12/30/2013'
Спасибо!
Комментарии:
1. В этом случае, IMO, важно, куда идет вывод этого запроса, потому что объединение данных таким образом не обязательно оптимально. Если вы планируете отображать для пользователя, то вы бы предпочли не комбинировать этот способ в запросе, а в пользовательском интерфейсе. Если это необходимо для перехода в другую базу данных, из вашего вопроса неясно, на какой основе объединяются данные. Вместо кода, пожалуйста, объясните на словах, как вы хотите, чтобы данные были объединены (т. Е. Как даты, выбранные для объединения в одной строке).
2. Привет, основная цель — получить среднее значение между выбранной ДАТОЙ и данными, эквивалентными сентябрю. Я обновлю изображение, чтобы описать, как выбрать строки для объединения.
3. Я не понимаю, как вы получаете доступ к данным. Вы начинаете с ’12/30/2013′. Для этой даты есть две записи. Почему вы отображаете 99, а не 0? Имеет ли это какое-то отношение к StoreID (который вы не используете в своем запросе)? И тогда как вы переходите от ’12/30/2013′ к ’09/30/2013′? Всегда ли последний день данного месяца минус три? Или как вы добираетесь до сентября и, в частности, до 30 сентября?
Ответ №1:
Выполните перекрестное объединение с той же таблицей и используйте свою структуру обращения только в предложении where:
SELECT a.DATE_FIELD AS DATE_FIELD_1,
a.ColA AS ColA_1,
b.DATE_FIELD AS DATE_FIELD_2,
b.ColA AS ColA_2
FROM TABLE_A a
CROSS JOIN TABLE_A b
WHERE DATE_FIELD_1 = 'your date'
AND DATE_FIELD_2 = (
CASE
WHEN MONTH(DATE_FIELD_1) < 10
THEN
(cast(CAST((YEAR(DATE_FIELD_1) - 1) as char(4)) RIGHT('00' LTRIM(09),2) RIGHT('00' LTRIM(30),2) AS Date))
ELSE
( cast(CAST((YEAR(DATE_FIELD_1)) as char(4)) RIGHT('00' LTRIM(09),2) RIGHT('00' LTRIM(30),2) AS Date))
END)
;
Другая возможность, основанная на замечаниях Торстена Кеттнера:
SELECT a.DATE_FIELD AS DATE_FIELD_1,
a.ColA AS ColA_1,
b.DATE_FIELD AS DATE_FIELD_2,
b.ColA AS ColA_2
FROM TABLE_A a
INNER JOIN TABLE_A b
ON b.DATE_FIELD = (
CASE
WHEN MONTH(a.DATE_FIELD) < 10
THEN
(cast(CAST((YEAR(a.DATE_FIELD) - 1) as char(4)) RIGHT('00' LTRIM(09),2) RIGHT('00' LTRIM(30),2) AS Date))
ELSE
( cast(CAST((YEAR(a.DATE_FIELD)) as char(4)) RIGHT('00' LTRIM(09),2) RIGHT('00' LTRIM(30),2) AS Date))
END)
WHERE a.DATE_FIELD = 'your date'
;
Комментарии:
1. Кстати, на самом деле это не перекрестное соединение. Это внутреннее соединение: И b .DATE_FIELD = (СЛУЧАЙ a .DATE_FIELD …) . Вместо этого вы должны использовать INNER JOIN и переместить предложение в ON, чтобы более четко показать, что вы делаете. Более того, на мой взгляд, вы немного запутываете ситуацию, используя DATE_FIELD_1 / 2 в вашем предложении WHERE, а не a / b.DATE_FIELD, который будет более четко показывать, как вы самостоятельно объединяете таблицу.
2. Ну, на мой взгляд, сначала это перекрестное соединение, а затем его строки ограничены теми, которые соответствуют моему предложению WHERE. Я неправильно это понимаю?
3. ДА. Перекрестное соединение — это когда вы соединяете две таблицы несвязанно . Вы создаете так называемое декартово произведение. Однако, когда вы соединяете две таблицы взаимосвязанно (есть критерии сопоставления их записей), вы фактически выполняете внутреннее соединение. Только вы скрываете это от читателя (например, чтобы имитировать устаревший синтаксис
FROM a, b WHERE a.x = b.y
). Не делайте этого.4. Некоторое время назад я попробовал ПЕРЕКРЕСТНОЕ СОЕДИНЕНИЕ, и оно сработало. И когда Торстен прокомментировал ВНУТРЕННЕЕ СОЕДИНЕНИЕ, это тоже сработало. Спасибо вам обоим!
5. Хорошо, спасибо за объяснение. Итак, остались ли какие-либо приложения для использования простого ПЕРЕКРЕСТНОГО соединения вообще?