Полезное руководство по преобразованию запросов из формата Microsoft SQL в Teradata SQL.
В приведенных примерах ссылка на объект «mufford» — это некое личное хранилище. Следует заменять на собственное.
Команда SELECT
Простой SELECT
SQL Server
1 2 3 4 5 6 | USE AdventureWorksDW2012; GO SELECT TOP 10 ProductKey , EnglishProductName FROM dbo.DimProduct; |
или
1 2 3 | SELECT TOP 10 ProductKey , EnglishProductName FROM AdventureWorksDW2012.dbo.DimProduct; |
Teradata
1 2 3 | SELECT TOP 10 P_PartKey , P_Name FROM retail.Product; |
Команда UPDATE
SQL Server
Чтобы продемонстрировать более сложный UPDATE, сначала будет создана временная таблица, добавлены данные в эту таблицу, а затем они будут модифицированы с помощью UPDATE.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | CREATE TABLE #UpdateTest_firstOrder ( ProductKey INT , FirstOrderNumber NVARCHAR(20) NULL ); INSERT INTO #UpdateTest_firstOrder(ProductKey) SELECT DISTINCT ProductKey FROM dbo.DimProduct; UPDATE ufo SET FirstOrderNumber = COALESCE(x.FirstOrderNumber, '-1') FROM #UpdateTest_firstOrder ufo JOIN ( SELECT ProductKey , MIN(SalesOrderNumber) AS FirstOrderNumber FROM dbo.FactInternetSales GROUP BY ProductKey ) AS x ON ufo.ProductKey = x.ProductKey; |
Teradata
Аналогичные манипуляции будут произведены в Teradata. Однако для этого есть два варианта, продемонстрированные ниже.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | CREATE VOLATILE TABLE UpdateTest_firstOrder ( L_PartKey INTEGER , FirstOrderKey INTEGER NULL ) PRIMARY INDEX ( L_PartKey ) ON COMMIT PRESERVE ROWS; INSERT INTO UpdateTest_firstOrder(L_PartKey) SELECT DISTINCT P_PartKey FROM retail.Product; -- Option 1 UPDATE UpdateTest_firstOrder FROM ( SELECT L_PartKey , MIN(L_OrderKey) AS FirstOrderKey FROM retail.Item GROUP BY L_PartKey ) AS x SET FirstOrderKey = COALESCE(x.FirstOrderKey, -1) WHERE UpdateTest_firstOrder.L_PartKey = x.L_PartKey; -- Option 2 UPDATE UpdateTest_firstOrder SET FirstOrderKey = FirstOrderKey WHERE EXISTS( SELECT L_PartKey , MIN(L_OrderKey) AS firstOrderID FROM retail.Item WHERE UpdateTest_firstOrder.L_PartKey = retail.Item.L_PartKey GROUP BY L_PartKey ); |
Команда DELETE
Delete Top X
SQL Server
Это довольно просто сделать в SQL Server.
1 2 3 | DELETE TOP (1) FROM dbo.DimEmployee WHERE BirthDate < '2012-01-01'; |
Teradata
В Teradata это немного сложнее. Нужно сначала создать временную таблицу, содержащую строки, которые нужно удалить. Затем выполнить DELETE используя оператор IN.
1 2 3 4 5 6 7 8 9 10 | CREATE TABLE mufford.ToBeDeleted AS ( SELECT TOP 1 EmpNo FROM retail.Employee WHERE DOB < DATE'2012-01-01' ) WITH DATA; DELETE FROM retail.Employee WHERE EmpNo IN (SELECT EmpNo FROM mufford.ToBeDeleted); |
Удаление с условием
SQL Server
1 2 3 4 5 | DELETE fis FROM dbo.FactInternetSales AS fis JOIN dbo.DimSalesTerritory AS dst ON fis.SalesTerritoryKey = dst.SalesTerritoryKey WHERE dst.SalesTerritoryCountry <> 'United States'; |
Teradata
Снова можно сделать удаление, воспользовавшись подзапросом.
1 2 3 4 5 6 7 | DELETE FROM retail.Item WHERE L_PartKey IN ( SELECT P_PartKey FROM retail.Product WHERE P_Mfgr = 'Manufacturer#1' ); |
Удаление, когда условие не выполняется
SQL Server
1 2 3 4 5 | DELETE fis FROM dbo.DimProduct AS dp LEFT JOIN dbo.FactInternetSales AS fis ON dp.ProductKey = fis.ProductKey WHERE fis.SalesOrderNumber IS NULL; |
Teradata
Опять используется подзапрос.
1 2 3 4 5 6 | DELETE FROM retail.Item WHERE NOT EXISTS( SELECT P_PartKey FROM retail.Product WHERE retail.Item.L_PartKey = retail.Product.P_PartKey ); |
Временные таблицы
Создание простой временной таблицы
SQL Server
Простой путь:
1 2 3 4 | SELECT LastName, FirstName INTO #MyTempTable FROM dbo.DimEmployee WHERE DepartmentName = 'Engineering'; |
Многословный «более практичный» вариант:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | CREATE TABLE #MyTempTable ( LastName NVARCHAR(50) , FirstName NVARCHAR(50) ); INSERT INTO #MyTempTable ( LastName , FirstName ) SELECT LastName , FirstName FROM dbo.DimEmployee WHERE DepartmentName = 'Engineering'; |
Teradata
В Teradata эквивалентом временных таблиц являются Volatile Tables.
1 2 3 4 5 6 7 | CREATE VOLATILE TABLE MyTempTable AS ( SELECT Name FROM retail.Employee WHERE DeptNo = 1420 ) WITH DATA ON COMMIT PRESERVE ROWS; |
Работа с датами
Найти за последние X дней
SQL Server
1 2 3 | SELECT SalesOrderNumber FROM dbo.FactInternetSales WHERE OrderDate >= DATEADD(day, -30, GETDATE()); |
Teradata
1 2 3 | SELECT L_OrderKey FROM retail.Item WHERE l_shipdate >= CURRENT_DATE - INTERVAL '30' DAY; |
Подсчет дней между двумя датами
SQL Server
1 2 3 4 5 6 7 8 9 | SELECT TOP 10 OrderDate , ShipDate , DATEDIFF(day, OrderDate, ShipDate) AS 'daysLapsed' FROM dbo.FactInternetSales; -- OR SELECT TOP 10 OrderDate , ShipDate , CAST(ShipDate - OrderDate AS INT) AS 'daysLapsed' FROM dbo.FactInternetSales; |
Teradata
1 2 3 4 | SELECT L_ShipDate , L_ReceiptDate , L_ReceiptDate - L_ShipDate AS "daysLapsed" FROM retail.Item; |
Использование дат в переменных
SQL Server
1 2 3 4 5 6 7 8 9 10 11 12 | CREATE PROCEDURE spReturnOrdersBetweenDaysExample ( @StartDate DATETIME , @EndDate DATETIME ) AS SELECT * FROM dbo.FactInternetSales WHERE OrderDate >= @StartDate AND OrderDate < @EndDate; EXECUTE spReturnOrdersBetweenDaysExample '2005-07-01', '2005-08-01'; |
Teradata
Вместо хранимой процедуры будем использовать макрос.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | CREATE MACRO mufford.mReturnOrdersBetweenDays ( startDate DATE , endDate DATE ) AS ( SELECT * FROM retail.Item WHERE L_ShipDate >= :startDate AND L_ShipDate < :endDate; ); EXECUTE mufford.mReturnOrdersBetweenDays('1993-09-01','1993-10-01'); |
Если появляется ошибка «An owner referenced by user does not have SELECT WITH GRANT OPTION» при попытке выполнить запрос выше,следует выполнить команду:
1 | GRANT SELECT ON retail.Item TO mufford WITH GRANT OPTION; |
Расчёт даты с использованием переменных
SQL Server
1 2 3 4 5 6 7 8 9 10 11 12 | CREATE PROCEDURE spReturnOrdersInXDaysExample ( @StartDate DATETIME , @numberOfDays INT ) AS SELECT * FROM dbo.FactInternetSales WHERE OrderDate >= @StartDate AND OrderDate < DATEADD(day, @numberOfDays, @StartDate); EXECUTE spReturnOrdersInXDaysExample '2005-07-01', 30; |
Teradata
В Teradata для получения того же типа даты будет использоваться макрос вместо хранимой процедуры.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | CREATE MACRO mufford.mReturnOrdersInXDaysExample ( startDate DATE DEFAULT CURRENT_DATE , numberOfDays INTEGER DEFAULT 30 ) AS ( SELECT * FROM retail.Item WHERE L_ShipDate >= :startDate AND L_ShipDate < :startDate + CAST(:numberOfDays AS INTERVAL DAY); ); EXECUTE mufford.mReturnOrdersInXDaysExample('1993-09-01', 30); |
Разное
Обработка NULL
SQL Server
1 2 | SELECT COALESCE(StandardCost, 0) AS [StandardCost] FROM dbo.DimProduct; |
или
1 2 | SELECT ISNULL(StandardCost, 0) AS [StandardCost] FROM dbo.DimProduct; |
Teradata
1 2 | SELECT COALESCE(P_RetailPrice, 0) AS "RetailPrice" FROM retail.Product; |
Язык Transact-SQL привязан к типам, и вы должны явно преобразовывать форматы там, где это необходимо. После команды cast в круглых скобках сначала указываем имя поля, которое нужно привести, а после ключевого слова as необходимо указать новый тип для поля.