#sql #create-table #days
#sql #создать таблицу #дни
Вопрос:
Привет, сообщество стеков,
Я не уверен, правильно ли я назвал это, но я пытаюсь создать таблицу, которая отслеживает ежедневное количество в использовании по коду продукта. В настоящее время мой код удаляет даты, когда продукт не используется, тогда как мне нужно, чтобы это отображалось как 0.
Мои мысли о том, что при использовании даты из таблицы date, что мое ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ с ISNULL в поле приведет к 0, но нет.
Вот мой код со скриншотом того, что он выводит, с выделением красного квадрата, где отсутствуют записи даты, которые мне нужно показать как 0 :
SELECT
DD.DATE,
DE.PRODUCT_CODE,
--OOC = OUT OF CONTEXT, EITHER ISN'T CHARGEABLE OR ISN'T CURRENTLY ACTIVE
ISNULL(SUM(LIDV.QTY - LIDV.QTYSUB),0),
OD.LOCATION,
OD.SOURCE
FROM Dim_Date AS DD
LEFT OUTER JOIN ORDERv_DatesDays AS OD ON DD.DATE BETWEEN OD.SHIP_DATE AND OD.adjRETURN_DATE
LEFT OUTER JOIN FACT_Orders_LIDs AS LIDV ON LIDV.SORDERID_DAX = OD.SORDERID_DAX
LEFT OUTER JOIN DIM_ECODES AS DE ON DE.PRODUCT_CODE = LIDV.eCODE
WHERE
--DD.DATE = '3/1/2017' AND
DD.DATE BETWEEN '1/1/2017' AND EOMONTH( DATEADD( MONTH , -1, CURRENT_TIMESTAMP ) ) AND
DE.PRODUCT_CODE = '07316-' AND
YEAR(DD.DATE) = 2017
GROUP BY
DD.DATE,
DE.PRODUCT_CODE,
OD.LOCATION,
OD.SOURCE
ORDER BY
DD.DATE
Я также подумал, поскольку я не эксперт по SQL, что, возможно, мне нужно просто создать таблицу с каждым кодом продукта и датой для указанного диапазона дат, но я запутался, пытаясь создать и это.
Спасибо за любую помощь, если мне нужно добавить больше информации, просто дайте мне знать, чего мне не хватает.
Комментарии:
1. Кстати, я рекомендую вам использовать даты в формате ‘2000-12-31’ в ваших жестко закодированных строковых константах
2. Почему запрос на скриншоте и запрос в вопросе отличаются?
3. Это не так, это то же самое, только без раздела «создать таблицу» и окончательного предложения order by.
4. И предложение where отличается.. Итак, тогда возникает вопрос: «к какому из этих разных запросов относится скриншот resultsgrid?»
Ответ №1:
Это ГДЕ предикат убивает ваше левое соединение:
DE.PRODUCT_CODE = '07316-' AND
Если product_code 07316 не был «предоставлен взаймы» (или что-то еще) в период с 24 февраля по 6 апреля, тогда все эти строки выглядели бы так:
DATE PRODUCT_CODE INUSE LOCATION
2017-02-25 NULL NULL NULL
2017-02-26 NULL NULL NULL
2017-02-27 NULL NULL NULL
2017-02-28 NULL NULL NULL
...
2017-04-05 NULL NULL NULL
Но это значение NULL in product_code
означает, что когда в предложении where задается вопрос «равно ли значение NULL 07316- ?», ответ является ложным, поэтому строка исчезает из результирующего набора
Рассмотрим
LEFT OUTER JOIN DIM_ECODES AS DE
ON
DE.PRODUCT_CODE = LIDV.eCODE AND
DE.PRODUCT_CODE = '07316-'
Возможно, вы также захотите внести некоторые изменения в блок ВЫБОРА:
'07316-' as PRODUCT_CODE,
COALESCE(INUSE,0) AS INUSE
Для вас может иметь больше смысла написать это так:
FROM
Dim_Date AS DD
LEFT OUTER JOIN
(
SELECT
OD.SHIP_DATE,
OD.adjRETURN_DATE,
LIDV.QTY,
LIDV.QTYSUB,
OD.LOCATION,
OD.SOURCE
FROM
ORDERv_DatesDays AS OD
INNER JOIN FACT_Orders_LIDs AS LIDV ON LIDV.SORDERID_DAX = OD.SORDERID_DAX
INNER JOIN DIM_ECODES AS DE ON DE.PRODUCT_CODE = LIDV.eCODE
WHERE
DE.PRODUCT_CODE = '07316-'
) x
ON DD.DATE BETWEEN x.SHIP_DATE AND x.adjRETURN_DATE
WHERE
Это «список дат слева» и «любые соответствующие данные, которые уже объединены и где справа»
Следует также отметить, что если вы делаете это для нескольких кодов продуктов, чтобы предотвратить только одну строку даты, если оба продукта 07316 и 07317 используются 28 февраля, вам необходимо:
FROM
(
SELECT DISTINCT DD.DATE, DE.PRODUCT_CODE
FROM Dim_Date AS DD CROSS JOIN DIM_ECODES DE
WHERE ..date range clause..
)
Это берет ваш список дат и пересекает его с вашим списком кодов продуктов, поэтому вы можете быть уверены, что есть хотя бы эти две строки:
2017-02-28 07316-
2017-02-28 07317-
Затем, когда вы слева соединяете продукты по дате и коду продукта, данные обеих этих строк сохраняются после левого соединения и становятся связанными с nulls:
2017-02-28 07316- NULL NULL
2017-02-28 07317- NULL NULL
Без этого ПЕРЕСЕЧЕНИЯ у вас будет только одна строка (null в коде продукта)
Комментарии:
1. Я специально использую этот код продукта (из более чем 300 тыс. кодов), поэтому у меня есть небольшой набор образцов, пока я работаю над своим кодом, вся моя таблица состоит из нескольких сотен миллионов строк. Результаты одинаковы, независимо от того, фильтрую ли я по этому коду в предложении WHERE или нет.
2. При условии, что эти строки действительно находятся в таблице dates, тогда эти строки где -то представлены, но у них нет кода продукта 07316, поэтому вы не можете найти их таким образом. Если вы запустите запрос без наличия кода продукта и получите свой
several hundred million rows
*your number of date rows
(т. Е. миллиарды строк), Вы все равно найдете их только один раз в результирующем наборе, если ни один продукт не был «в использовании» в эти даты3. Ваш метод «я хочу, чтобы в 2017 году были все 365 дат, плюс только те дни, когда продукты совпадают» является правильным (
dates LEFT JOIN products WHERE date in 2017
), но упоминание в предложении WHERE любой таблицы, которая находится справа от «левого соединения», преобразует соединение во внутреннее (эффективно), потому что все нулиЛЕВЫЕ вводные элементы удаляются с помощью WHERE . Любое из ваших других объединений может завершиться неудачно, и даты будут сохранены.. если только они не будут отфильтрованы впоследствии4. Да, недостающие даты указаны в таблице дат, но, как вы правильно предположили, у меня нет используемых данных для кода продукта для некоторых дат, поэтому я пытаюсь представить 0 для тех неиспользуемых дат (если это имеет смысл). Комментарий в несколько сотен миллионов строк — это таблица со всеми кодами наших продуктов, в которой отсутствуют только даты, подобные тем, что на скриншоте. После этого не было бы миллиардов. Не знал, что в предложении left join и RIGHT table where, СПАСИБО!
5. Добавлено еще одно замечание о том, делаете ли вы это для нескольких продуктов; это может быть важно для вас, чтобы рассмотреть